Index: include/private/GrSurfaceProxy.h |
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h |
index dd5ece1e2c025ca66040f40ea979cda976d13095..1ff6df809d3de913c60b397391c7e475583947fc 100644 |
--- a/include/private/GrSurfaceProxy.h |
+++ b/include/private/GrSurfaceProxy.h |
@@ -50,13 +50,29 @@ public: |
void validate() const { |
#ifdef SK_DEBUG |
- SkASSERT(fRefCnt >= 0); |
+ SkASSERT(fRefCnt >= 1); |
+ SkASSERT(fPendingReads >= 0); |
+ SkASSERT(fPendingWrites >= 0); |
+ SkASSERT(fRefCnt + fPendingReads + fPendingWrites >= 1); |
+ |
+ if (fTarget) { |
+ SkASSERT(!fPendingReads && !fPendingWrites); |
+ // The backing GrSurface can have more refs than the proxy if the proxy |
+ // started off wrapping an external resource (that came in with refs). |
+ // The GrSurface should never have fewer refs than the proxy however. |
+ SkASSERT(fTarget->fRefCnt >= fRefCnt); |
+ } |
#endif |
} |
+ int32_t getProxyRefCnt_TestOnly() const; |
+ int32_t getBackingRefCnt_TestOnly() const; |
+ int32_t getPendingReadCnt_TestOnly() const; |
+ int32_t getPendingWriteCnt_TestOnly() const; |
+ |
protected: |
- GrIORefProxy() : fRefCnt(1), fTarget(nullptr) {} |
- GrIORefProxy(sk_sp<GrSurface> surface) : fRefCnt(1) { |
+ GrIORefProxy() : fTarget(nullptr), fRefCnt(1), fPendingReads(0), fPendingWrites(0) {} |
+ GrIORefProxy(sk_sp<GrSurface> surface) : fRefCnt(1), fPendingReads(0), fPendingWrites(0) { |
// Since we're manually forwarding on refs & unrefs we don't want sk_sp doing |
// anything extra. |
fTarget = surface.release(); |
@@ -66,13 +82,76 @@ protected: |
// have forwarded on the unref call that got use here. |
} |
- // TODO: add the IO ref counts. Although if we can delay shader creation to flush time |
- // we may not even need to do that. |
- mutable int32_t fRefCnt; |
+ // This GrIORefProxy was deferred before but has just been instantiated. To |
+ // make all the reffing & unreffing work out we now need to transfer any deferred |
+ // refs & unrefs to the new GrSurface |
+ void transferRefs() { |
+ SkASSERT(fTarget); |
+ |
+ fTarget->fRefCnt += (fRefCnt-1); // don't xfer the proxy's creation ref |
+ fTarget->fPendingReads += fPendingReads; |
+ fTarget->fPendingWrites += fPendingWrites; |
+ |
+ fPendingReads = 0; |
+ fPendingWrites = 0; |
+ } |
// For deferred proxies this will be null. For wrapped proxies it will point to the |
// wrapped resource. |
GrSurface* fTarget; |
+ |
+private: |
+ // This class is used to manage conversion of refs to pending reads/writes. |
+ friend class GrGpuResourceRef; |
+ template <typename, GrIOType> friend class GrPendingIOResource; |
+ |
+ void addPendingRead() const { |
+ this->validate(); |
+ |
+ if (fTarget) { |
+ fTarget->addPendingRead(); |
+ return; |
+ } |
+ |
+ ++fPendingReads; |
+ } |
+ |
+ void completedRead() const { |
+ this->validate(); |
+ |
+ if (fTarget) { |
+ fTarget->completedRead(); |
+ return; |
+ } |
+ |
+ SkFAIL("How was the read completed if the Proxy hasn't been instantiated?"); |
+ } |
+ |
+ void addPendingWrite() const { |
+ this->validate(); |
+ |
+ if (fTarget) { |
+ fTarget->addPendingWrite(); |
+ return; |
+ } |
+ |
+ ++fPendingWrites; |
+ } |
+ |
+ void completedWrite() const { |
+ this->validate(); |
+ |
+ if (fTarget) { |
+ fTarget->completedWrite(); |
+ return; |
+ } |
+ |
+ SkFAIL("How was the write completed if the Proxy hasn't been instantiated?"); |
+ } |
+ |
+ mutable int32_t fRefCnt; |
+ mutable int32_t fPendingReads; |
+ mutable int32_t fPendingWrites; |
}; |
class GrSurfaceProxy : public GrIORefProxy { |