| 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 {
|
|
|