1 /* 2 * Copyright 2018 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrProxyRef_DEFINED 9 #define GrProxyRef_DEFINED 10 11 #include "GrSurfaceProxy.h" 12 #include "GrTextureProxy.h" 13 #include "GrTypesPriv.h" 14 15 /** 16 * Helper for owning a ref and/or pending IO on a GrSurfaceProxy. This is useful when ownership 17 * must transform from ref'ed to pending IO when the owner is recorded into a GrOpList. 18 */ 19 template <typename T> class GrProxyRef { 20 public: 21 GrProxyRef() = default; 22 GrProxyRef(const GrProxyRef&) = delete; 23 GrProxyRef& operator=(const GrProxyRef&) = delete; 24 25 /** ioType expresses what type of IO operations will be marked as pending on the proxy when 26 markPendingIO is called. */ GrProxyRef(sk_sp<T> proxy,GrIOType ioType)27 GrProxyRef(sk_sp<T> proxy, GrIOType ioType) { this->setProxy(std::move(proxy), ioType); } 28 ~GrProxyRef()29 ~GrProxyRef() { this->reset(); } 30 31 /** ioType expresses what type of IO operations will be marked as 32 pending on the proxy when markPendingIO is called. */ setProxy(sk_sp<T> proxy,GrIOType ioType)33 void setProxy(sk_sp<T> proxy, GrIOType ioType) { 34 SkASSERT(!fPendingIO); 35 SkASSERT(SkToBool(fProxy) == fOwnRef); 36 SkSafeUnref(fProxy); 37 if (!proxy) { 38 fProxy = nullptr; 39 fOwnRef = false; 40 } else { 41 fProxy = proxy.release(); // due to the semantics of this class we unpack from sk_sp 42 fOwnRef = true; 43 fIOType = ioType; 44 } 45 } 46 get()47 T* get() const { return fProxy; } 48 49 /** Does this object own a pending read or write on the resource it is wrapping. */ ownsPendingIO()50 bool ownsPendingIO() const { return fPendingIO; } 51 52 /** What type of IO does this represent? This is independent of whether a normal ref or a 53 pending IO is currently held. */ ioType()54 GrIOType ioType() const { return fIOType; } 55 56 /** Shortcut for calling setProxy() with NULL. It cannot be called after markingPendingIO 57 is called. */ reset()58 void reset() { 59 if (fPendingIO) { 60 SkASSERT(fProxy); 61 switch (fIOType) { 62 case kRead_GrIOType: 63 fProxy->completedRead(); 64 break; 65 case kWrite_GrIOType: 66 fProxy->completedWrite(); 67 break; 68 case kRW_GrIOType: 69 fProxy->completedRead(); 70 fProxy->completedWrite(); 71 break; 72 } 73 fPendingIO = false; 74 } 75 if (fOwnRef) { 76 SkASSERT(fProxy); 77 fProxy->unref(); 78 fOwnRef = false; 79 } 80 fProxy = nullptr; 81 } 82 83 /** 84 * Called when transferring into an op list and therefore scheduled for an IO operation. It can 85 * only be called once. 86 */ markPendingIO()87 void markPendingIO() const { 88 // This should only be called when the owning GrProgramElement gets its first 89 // pendingExecution ref. 90 SkASSERT(!fPendingIO); 91 SkASSERT(fProxy); 92 fPendingIO = true; 93 switch (fIOType) { 94 case kRead_GrIOType: 95 fProxy->addPendingRead(); 96 break; 97 case kWrite_GrIOType: 98 fProxy->addPendingWrite(); 99 break; 100 case kRW_GrIOType: 101 fProxy->addPendingRead(); 102 fProxy->addPendingWrite(); 103 break; 104 } 105 } 106 107 /** Called when the program element/draw state is no longer owned by GrOpList-client code. 108 This lets the cache know that the drawing code will no longer schedule additional reads or 109 writes to the resource using the program element or draw state. It can only be called once. 110 */ removeRef()111 void removeRef() const { 112 SkASSERT(fOwnRef); 113 SkASSERT(fPendingIO); 114 SkASSERT(fProxy); 115 fProxy->unref(); 116 fOwnRef = false; 117 } 118 119 /** Called to indicate that the previous pending IO is complete. Useful when the owning object 120 still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously 121 pending executions have been complete. Can only be called if removeRef() was not previously 122 called. */ pendingIOComplete()123 void pendingIOComplete() const { 124 SkASSERT(fOwnRef); 125 SkASSERT(fPendingIO); 126 switch (fIOType) { 127 case kRead_GrIOType: 128 fProxy->completedRead(); 129 break; 130 case kWrite_GrIOType: 131 fProxy->completedWrite(); 132 break; 133 case kRW_GrIOType: 134 fProxy->completedRead(); 135 fProxy->completedWrite(); 136 break; 137 } 138 fPendingIO = false; 139 } 140 141 private: 142 T* fProxy = nullptr; 143 mutable bool fOwnRef = false; 144 mutable bool fPendingIO = false; 145 GrIOType fIOType = kRead_GrIOType; 146 }; 147 148 using GrSurfaceProxyRef = GrProxyRef<GrSurfaceProxy>; 149 using GrTextureProxyRef = GrProxyRef<GrTextureProxy>; 150 151 #endif 152