Add method to GrProgramResource to record that pending a execution was completed.

BUG=skia:2889
R=robertphillips@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/543833002
diff --git a/include/gpu/GrGpuResource.h b/include/gpu/GrGpuResource.h
index 189237a..d117c42 100644
--- a/include/gpu/GrGpuResource.h
+++ b/include/gpu/GrGpuResource.h
@@ -109,8 +109,7 @@
     mutable int32_t fPendingReads;
     mutable int32_t fPendingWrites;
 
-    // These functions need access to the pending read/write member functions.
-    friend class GrRODrawState;
+    // This class is used to manage conversion of refs to pending reads/writes.
     friend class GrProgramResource;
 };
 
diff --git a/include/gpu/GrProgramElement.h b/include/gpu/GrProgramElement.h
index 67135a3..6fdc98d 100644
--- a/include/gpu/GrProgramElement.h
+++ b/include/gpu/GrProgramElement.h
@@ -71,13 +71,7 @@
 private:
     void convertRefToPendingExecution() const;
 
-    void completedExecution() const {
-        this->validate();
-        --fPendingExecutions;
-        if (0 == fRefCnt && 0 == fPendingExecutions) {
-            SkDELETE(this);
-        }
-    }
+    void completedExecution() const;
 
     mutable int32_t fRefCnt;
     // Count of deferred executions not yet issued to the 3D API.
diff --git a/include/gpu/GrProgramResource.h b/include/gpu/GrProgramResource.h
index 277ae9d..61e71de 100644
--- a/include/gpu/GrProgramResource.h
+++ b/include/gpu/GrProgramResource.h
@@ -59,7 +59,13 @@
         writes to the resource using the program element or draw state. */
     void removeRef() const;
 
-    friend class GrDrawState;
+    /** 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 GrProgramResource, but its previously
+        pending executions have been complete.
+     */
+    void pendingIOComplete() const;
+
+    friend class GrRODrawState;
     friend class GrProgramElement;
 
     GrGpuResource*      fResource;
diff --git a/src/gpu/GrProgramElement.cpp b/src/gpu/GrProgramElement.cpp
index e14a85b..70d5339 100644
--- a/src/gpu/GrProgramElement.cpp
+++ b/src/gpu/GrProgramElement.cpp
@@ -5,7 +5,6 @@
  * found in the LICENSE file.
  */
 
-
 #include "GrProgramElement.h"
 #include "GrProgramResource.h"
 
@@ -28,3 +27,20 @@
         }
     }
 }
+
+void GrProgramElement::completedExecution() const {
+    this->validate();
+    --fPendingExecutions;
+    if (0 == fPendingExecutions) {
+        if (0 == fRefCnt) {
+            SkDELETE(this);
+        } else {
+            // Now our pending executions have ocurred and we still have refs. Convert
+            // ownership of our resources back to regular refs.
+            for (int i = 0; i < fProgramResources.count(); ++i) {
+                fProgramResources[i]->pendingIOComplete();
+            }
+
+        }
+    }
+}
diff --git a/src/gpu/GrProgramResource.cpp b/src/gpu/GrProgramResource.cpp
index 08975ae..3bf25a1 100644
--- a/src/gpu/GrProgramResource.cpp
+++ b/src/gpu/GrProgramResource.cpp
@@ -74,7 +74,7 @@
 }
 
 void GrProgramResource::markPendingIO() const {
-    // This should only be called once, when the owning GrProgramElement gets its first
+    // This should only be called when the owning GrProgramElement gets its first
     // pendingExecution ref.
     SkASSERT(!fPendingIO);
     SkASSERT(NULL != fResource);
@@ -97,6 +97,30 @@
     }
 }
 
+void GrProgramResource::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 kNone_IOType:
+            SkFAIL("GrProgramResource with neither reads nor writes?");
+            break;
+        case kRead_IOType:
+            fResource->completedRead();
+            break;
+        case kWrite_IOType:
+            fResource->completedWrite();
+            break;
+        case kRW_IOType:
+            fResource->completedRead();
+            fResource->completedWrite();
+            break;
+
+    }
+    fPendingIO = false;
+}
+
 void GrProgramResource::removeRef() const {
     // This should only be called once, when the owners last ref goes away and
     // there is a pending execution.