templatize GrSurfaceProxyRef

Change-Id: I23e848d852a0c126a6581d2682af3f9e927e876f
Reviewed-on: https://skia-review.googlesource.com/144607
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 45aafa5..2c1f338 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -36,10 +36,10 @@
   "$_include/private/GrCCClipPath.h",
   "$_include/private/GrCCPerOpListPaths.h",
   "$_include/private/GrOpList.h",
+  "$_include/private/GrProxyRef.h",
   "$_include/private/GrSingleOwner.h",
   "$_include/private/GrRenderTargetProxy.h",
   "$_include/private/GrSurfaceProxy.h",
-  "$_include/private/GrSurfaceProxyRef.h",
   "$_include/private/GrTextureProxy.h",
   "$_include/private/GrTypesPriv.h",
 
@@ -187,7 +187,6 @@
   "$_src/gpu/GrStyle.h",
   "$_src/gpu/GrSurfaceContextPriv.h",
   "$_src/gpu/GrSurfaceProxyPriv.h",
-  "$_src/gpu/GrSurfaceProxyRef.cpp",
   "$_src/gpu/GrSwizzle.h",
   "$_src/gpu/GrTessellator.cpp",
   "$_src/gpu/GrTessellator.h",
diff --git a/include/private/GrOpList.h b/include/private/GrOpList.h
index be7389f..26d3365 100644
--- a/include/private/GrOpList.h
+++ b/include/private/GrOpList.h
@@ -9,7 +9,7 @@
 #define GrOpList_DEFINED
 
 #include "GrColor.h"
-#include "GrSurfaceProxyRef.h"
+#include "GrProxyRef.h"
 #include "GrTextureProxy.h"
 #include "SkRefCnt.h"
 #include "SkTDArray.h"
diff --git a/include/private/GrProxyRef.h b/include/private/GrProxyRef.h
new file mode 100644
index 0000000..7af6ec4
--- /dev/null
+++ b/include/private/GrProxyRef.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrProxyRef_DEFINED
+#define GrProxyRef_DEFINED
+
+#include "GrSurfaceProxy.h"
+#include "GrTextureProxy.h"
+#include "GrTypesPriv.h"
+
+/**
+ * Helper for owning a ref and/or pending IO on a GrSurfaceProxy. This is useful when ownership
+ * must transform from ref'ed to pending IO when the owner is recorded into a GrOpList.
+ */
+template <typename T> class GrProxyRef {
+public:
+    GrProxyRef() = default;
+    GrProxyRef(const GrProxyRef&) = delete;
+    GrProxyRef& operator=(const GrProxyRef&) = delete;
+
+    /** ioType expresses what type of IO operations will be marked as pending on the proxy when
+        markPendingIO is called. */
+    GrProxyRef(sk_sp<T> proxy, GrIOType ioType) { this->setProxy(std::move(proxy), ioType); }
+
+    ~GrProxyRef() { this->reset(); }
+
+    /** ioType expresses what type of IO operations will be marked as
+        pending on the proxy when markPendingIO is called. */
+    void setProxy(sk_sp<T> proxy, GrIOType ioType) {
+        SkASSERT(!fPendingIO);
+        SkASSERT(SkToBool(fProxy) == fOwnRef);
+        SkSafeUnref(fProxy);
+        if (!proxy) {
+            fProxy = nullptr;
+            fOwnRef = false;
+        } else {
+            fProxy = proxy.release();  // due to the semantics of this class we unpack from sk_sp
+            fOwnRef = true;
+            fIOType = ioType;
+        }
+    }
+
+    T* get() const { return fProxy; }
+
+    /** Does this object own a pending read or write on the resource it is wrapping. */
+    bool ownsPendingIO() const { return fPendingIO; }
+
+    /** What type of IO does this represent? This is independent of whether a normal ref or a
+        pending IO is currently held. */
+    GrIOType ioType() const { return fIOType; }
+
+    /** Shortcut for calling setProxy() with NULL. It cannot be called after markingPendingIO
+        is called. */
+    void reset() {
+        if (fPendingIO) {
+            SkASSERT(fProxy);
+            switch (fIOType) {
+                case kRead_GrIOType:
+                    fProxy->completedRead();
+                    break;
+                case kWrite_GrIOType:
+                    fProxy->completedWrite();
+                    break;
+                case kRW_GrIOType:
+                    fProxy->completedRead();
+                    fProxy->completedWrite();
+                    break;
+            }
+            fPendingIO = false;
+        }
+        if (fOwnRef) {
+            SkASSERT(fProxy);
+            fProxy->unref();
+            fOwnRef = false;
+        }
+        fProxy = nullptr;
+    }
+
+    /** Called by owning GrProgramElement when the program element is first scheduled for
+        execution. It can only be called once. */
+    void markPendingIO() const {
+        // This should only be called when the owning GrProgramElement gets its first
+        // pendingExecution ref.
+        SkASSERT(!fPendingIO);
+        SkASSERT(fProxy);
+        fPendingIO = true;
+        switch (fIOType) {
+            case kRead_GrIOType:
+                fProxy->addPendingRead();
+                break;
+            case kWrite_GrIOType:
+                fProxy->addPendingWrite();
+                break;
+            case kRW_GrIOType:
+                fProxy->addPendingRead();
+                fProxy->addPendingWrite();
+                break;
+        }
+    }
+
+    /** Called when the program element/draw state is no longer owned by GrOpList-client code.
+        This lets the cache know that the drawing code will no longer schedule additional reads or
+        writes to the resource using the program element or draw state. It can only be called once.
+      */
+    void removeRef() const {
+        SkASSERT(fOwnRef);
+        SkASSERT(fPendingIO);
+        SkASSERT(fProxy);
+        fProxy->unref();
+        fOwnRef = false;
+    }
+
+    /** Called to indicate that the previous pending IO is complete. Useful when the owning object
+        still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously
+        pending executions have been complete. Can only be called if removeRef() was not previously
+        called. */
+    void pendingIOComplete() const {
+        SkASSERT(fOwnRef);
+        SkASSERT(fPendingIO);
+        switch (fIOType) {
+            case kRead_GrIOType:
+                fProxy->completedRead();
+                break;
+            case kWrite_GrIOType:
+                fProxy->completedWrite();
+                break;
+            case kRW_GrIOType:
+                fProxy->completedRead();
+                fProxy->completedWrite();
+                break;
+        }
+        fPendingIO = false;
+    }
+
+private:
+    T*              fProxy = nullptr;
+    mutable bool    fOwnRef = false;
+    mutable bool    fPendingIO = false;
+    GrIOType        fIOType = kRead_GrIOType;
+};
+
+using GrSurfaceProxyRef = GrProxyRef<GrSurfaceProxy>;
+using GrTextureProxyRef = GrProxyRef<GrTextureProxy>;
+
+#endif
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
index 425b183..5a50314 100644
--- a/include/private/GrSurfaceProxy.h
+++ b/include/private/GrSurfaceProxy.h
@@ -189,8 +189,7 @@
 
 private:
     // This class is used to manage conversion of refs to pending reads/writes.
-    friend class GrSurfaceProxyRef;
-    template <typename, GrIOType> friend class GrPendingIOResource;
+    template <typename> friend class GrProxyRef;
 
     void didRemoveRefOrPendingIO() const {
         if (0 == fPendingReads && 0 == fPendingWrites && 0 == fRefCnt) {
diff --git a/include/private/GrSurfaceProxyRef.h b/include/private/GrSurfaceProxyRef.h
deleted file mode 100644
index fb2ed37..0000000
--- a/include/private/GrSurfaceProxyRef.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrSurfaceProxyRef_DEFINED
-#define GrSurfaceProxyRef_DEFINED
-
-#include "../private/SkNoncopyable.h"
-#include "GrTypesPriv.h"
-
-class GrSurfaceProxy;
-
-class GrSurfaceProxyRef : SkNoncopyable {
-public:
-    GrSurfaceProxyRef();
-
-    /** ioType expresses what type of IO operations will be marked as
-        pending on the resource when markPendingIO is called. */
-    GrSurfaceProxyRef(sk_sp<GrSurfaceProxy>, GrIOType);
-
-    ~GrSurfaceProxyRef();
-
-    /** ioType expresses what type of IO operations will be marked as
-        pending on the resource when markPendingIO is called. */
-    void setProxy(sk_sp<GrSurfaceProxy>, GrIOType);
-
-    GrSurfaceProxy* get() const { return fProxy; }
-
-    /** Does this object own a pending read or write on the resource it is wrapping. */
-    bool ownsPendingIO() const { return fPendingIO; }
-
-    /** What type of IO does this represent? This is independent of whether a normal ref or a
-        pending IO is currently held. */
-    GrIOType ioType() const { return fIOType; }
-
-    /** Shortcut for calling setProxy() with NULL. It cannot be called after markingPendingIO
-        is called. */
-    void reset();
-
-    /** Called by owning GrProgramElement when the program element is first scheduled for
-        execution. It can only be called once. */
-    void markPendingIO() const;
-
-    /** Called when the program element/draw state is no longer owned by GrOpList-client code.
-        This lets the cache know that the drawing code will no longer schedule additional reads or
-        writes to the resource using the program element or draw state. It can only be called once.
-      */
-    void removeRef() const;
-
-    /** Called to indicate that the previous pending IO is complete. Useful when the owning object
-        still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously
-        pending executions have been complete. Can only be called if removeRef() was not previously
-        called. */
-    void pendingIOComplete() const;
-
-private:
-    GrSurfaceProxy* fProxy;
-    mutable bool    fOwnRef;
-    mutable bool    fPendingIO;
-    GrIOType        fIOType;
-
-    typedef SkNoncopyable INHERITED;
-};
-
-#endif
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index 081aff3..33cde77 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -92,9 +92,9 @@
 
 void GrFragmentProcessor::markPendingExecution() const {
     for (int i = 0; i < fTextureSamplerCnt; ++i) {
-        auto* proxy = this->textureSampler(i).programProxy();
-        proxy->markPendingIO();
-        proxy->removeRef();
+        auto* ref = this->textureSampler(i).proxyRef();
+        ref->markPendingIO();
+        ref->removeRef();
     }
     for (int i = 0; i < this->numChildProcessors(); ++i) {
         this->childProcessor(i).markPendingExecution();
diff --git a/src/gpu/GrFragmentProcessor.h b/src/gpu/GrFragmentProcessor.h
index 9075015..5b9ce24 100644
--- a/src/gpu/GrFragmentProcessor.h
+++ b/src/gpu/GrFragmentProcessor.h
@@ -9,10 +9,10 @@
 #define GrFragmentProcessor_DEFINED
 
 #include "GrProcessor.h"
+#include "GrProxyRef.h"
 
 class GrCoordTransform;
 class GrGLSLFragmentProcessor;
-class GrInvariantOutput;
 class GrPaint;
 class GrPipeline;
 class GrProcessorKeyBuilder;
@@ -441,17 +441,17 @@
         return fProxyRef.get()->peekTexture();
     }
 
-    GrTextureProxy* proxy() const { return fProxyRef.get()->asTextureProxy(); }
+    GrTextureProxy* proxy() const { return fProxyRef.get(); }
     const GrSamplerState& samplerState() const { return fSamplerState; }
 
     bool isInitialized() const { return SkToBool(fProxyRef.get()); }
     /**
      * For internal use by GrFragmentProcessor.
      */
-    const GrSurfaceProxyRef* programProxy() const { return &fProxyRef; }
+    const GrTextureProxyRef* proxyRef() const { return &fProxyRef; }
 
 private:
-    GrSurfaceProxyRef fProxyRef;
+    GrTextureProxyRef fProxyRef;
     GrSamplerState fSamplerState;
 };
 
diff --git a/src/gpu/GrPrimitiveProcessor.cpp b/src/gpu/GrPrimitiveProcessor.cpp
index 10b1337..84db9ca 100644
--- a/src/gpu/GrPrimitiveProcessor.cpp
+++ b/src/gpu/GrPrimitiveProcessor.cpp
@@ -76,19 +76,19 @@
 
 void GrPrimitiveProcessor::addPendingIOs() const {
     for (int i = 0; i < fTextureSamplerCnt; ++i) {
-        this->textureSampler(i).programProxy()->markPendingIO();
+        this->textureSampler(i).proxyRef()->markPendingIO();
     }
 }
 
 void GrPrimitiveProcessor::removeRefs() const {
     for (int i = 0; i < fTextureSamplerCnt; ++i) {
-        this->textureSampler(i).programProxy()->removeRef();
+        this->textureSampler(i).proxyRef()->removeRef();
     }
 }
 
 void GrPrimitiveProcessor::pendingIOComplete() const {
     for (int i = 0; i < fTextureSamplerCnt; ++i) {
-        this->textureSampler(i).programProxy()->pendingIOComplete();
+        this->textureSampler(i).proxyRef()->pendingIOComplete();
     }
 }
 
diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h
index 20471ea..ddebd21 100644
--- a/src/gpu/GrPrimitiveProcessor.h
+++ b/src/gpu/GrPrimitiveProcessor.h
@@ -10,6 +10,7 @@
 
 #include "GrColor.h"
 #include "GrProcessor.h"
+#include "GrProxyRef.h"
 #include "GrShaderVar.h"
 
 class GrCoordTransform;
@@ -216,7 +217,7 @@
         return fProxyRef.get()->peekTexture();
     }
 
-    GrTextureProxy* proxy() const { return fProxyRef.get()->asTextureProxy(); }
+    GrTextureProxy* proxy() const { return fProxyRef.get(); }
     GrShaderFlags visibility() const { return fVisibility; }
     const GrSamplerState& samplerState() const { return fSamplerState; }
 
@@ -224,10 +225,10 @@
     /**
      * For internal use by GrPrimitiveProcessor.
      */
-    const GrSurfaceProxyRef* programProxy() const { return &fProxyRef; }
+    const GrTextureProxyRef* proxyRef() const { return &fProxyRef; }
 
 private:
-    GrSurfaceProxyRef fProxyRef;
+    GrTextureProxyRef fProxyRef;
     GrSamplerState fSamplerState;
     GrShaderFlags fVisibility = kNone_GrShaderFlags;
 };
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index 1c0161a..4afb246 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -16,7 +16,6 @@
 #include "GrSamplerState.h"
 #include "GrShaderVar.h"
 #include "GrSurfaceProxyPriv.h"
-#include "GrSurfaceProxyRef.h"
 #include "GrTextureProxy.h"
 #include "SkMath.h"
 #include "SkString.h"
diff --git a/src/gpu/GrSurfaceProxyRef.cpp b/src/gpu/GrSurfaceProxyRef.cpp
deleted file mode 100644
index ad13e4a..0000000
--- a/src/gpu/GrSurfaceProxyRef.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrSurfaceProxyRef.h"
-#include "GrTextureProxy.h"
-
-GrSurfaceProxyRef::GrSurfaceProxyRef() {
-    fProxy = nullptr;
-    fOwnRef = false;
-    fPendingIO = false;
-}
-
-GrSurfaceProxyRef::GrSurfaceProxyRef(sk_sp<GrSurfaceProxy> proxy, GrIOType ioType) {
-    fProxy = nullptr;
-    fOwnRef = false;
-    fPendingIO = false;
-    this->setProxy(std::move(proxy), ioType);
-}
-
-GrSurfaceProxyRef::~GrSurfaceProxyRef() {
-    this->reset();
-}
-
-void GrSurfaceProxyRef::reset() {
-    if (fPendingIO) {
-        SkASSERT(fProxy);
-        switch (fIOType) {
-            case kRead_GrIOType:
-                fProxy->completedRead();
-                break;
-            case kWrite_GrIOType:
-                fProxy->completedWrite();
-                break;
-            case kRW_GrIOType:
-                fProxy->completedRead();
-                fProxy->completedWrite();
-                break;
-        }
-        fPendingIO = false;
-    }
-    if (fOwnRef) {
-        SkASSERT(fProxy);
-        fProxy->unref();
-        fOwnRef = false;
-    }
-
-    fProxy = nullptr;
-}
-
-void GrSurfaceProxyRef::setProxy(sk_sp<GrSurfaceProxy> proxy, GrIOType ioType) {
-    SkASSERT(!fPendingIO);
-    SkASSERT(SkToBool(fProxy) == fOwnRef);
-    SkSafeUnref(fProxy);
-    if (!proxy) {
-        fProxy = nullptr;
-        fOwnRef = false;
-    } else {
-        fProxy = proxy.release();   // due to the semantics of this class we unpack from sk_sp
-        fOwnRef = true;
-        fIOType = ioType;
-    }
-}
-
-void GrSurfaceProxyRef::markPendingIO() const {
-    // This should only be called when the owning GrProgramElement gets its first
-    // pendingExecution ref.
-    SkASSERT(!fPendingIO);
-    SkASSERT(fProxy);
-    fPendingIO = true;
-    switch (fIOType) {
-        case kRead_GrIOType:
-            fProxy->addPendingRead();
-            break;
-        case kWrite_GrIOType:
-            fProxy->addPendingWrite();
-            break;
-        case kRW_GrIOType:
-            fProxy->addPendingRead();
-            fProxy->addPendingWrite();
-            break;
-    }
-}
-
-void GrSurfaceProxyRef::pendingIOComplete() const {
-    // This should only be called when the owner's pending executions have ocurred but it is still
-    // reffed.
-    SkASSERT(fOwnRef);
-    SkASSERT(fPendingIO);
-    switch (fIOType) {
-        case kRead_GrIOType:
-            fProxy->completedRead();
-            break;
-        case kWrite_GrIOType:
-            fProxy->completedWrite();
-            break;
-        case kRW_GrIOType:
-            fProxy->completedRead();
-            fProxy->completedWrite();
-            break;
-
-    }
-    fPendingIO = false;
-}
-
-void GrSurfaceProxyRef::removeRef() const {
-    // This should only be called once, when the owners last ref goes away and
-    // there is a pending execution.
-    SkASSERT(fOwnRef);
-    SkASSERT(fPendingIO);
-    SkASSERT(fProxy);
-    fProxy->unref();
-    fOwnRef = false;
-}
-