1 /* 2 * Copyright 2014 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 GrGpuResourceRef_DEFINED 9 #define GrGpuResourceRef_DEFINED 10 11 #include "GrGpuResource.h" 12 #include "SkRefCnt.h" 13 14 /** 15 * This class is intended only for internal use in core Gr code. 16 * 17 * Class that wraps a resource referenced by a GrProgramElement or GrDrawState. It manages 18 * converting refs to pending IO operations. It allows a resource ownership to be in three 19 * states: 20 * 1. Owns a single ref 21 * 2. Owns a single ref and a pending IO operation (read, write, or read-write) 22 * 3. Owns a single pending IO operation. 23 * 24 * It is legal to destroy the GrGpuResourceRef in any of these states. It starts in state 25 * 1. Calling markPendingIO() converts it from state 1 to state 2. Calling removeRef() goes from 26 * state 2 to state 3. Calling pendingIOComplete() moves from state 2 to state 1. There is no 27 * valid way of going from state 3 back to 2 or 1. 28 * 29 * Like sk_sp, its constructor and setter adopt a ref from their caller. 30 * 31 * TODO: Once GrDODrawState no longer exists and therefore GrDrawState and GrOptDrawState no 32 * longer share an instance of this class, attempt to make the resource owned by GrGpuResourceRef 33 * only settable via the constructor. 34 */ 35 class GrGpuResourceRef : SkNoncopyable { 36 public: 37 ~GrGpuResourceRef(); 38 39 GrGpuResource* getResource() const { return fResource; } 40 41 /** Does this object own a pending read or write on the resource it is wrapping. */ 42 bool ownsPendingIO() const { return fPendingIO; } 43 44 /** What type of IO does this represent? This is independent of whether a normal ref or a 45 pending IO is currently held. */ 46 GrIOType ioType() const { return fIOType; } 47 48 /** Shortcut for calling setResource() with NULL. It cannot be called after markingPendingIO 49 is called. */ 50 void reset(); 51 52 protected: 53 GrGpuResourceRef(); 54 55 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 56 pending on the resource when markPendingIO is called. */ 57 GrGpuResourceRef(GrGpuResource*, GrIOType); 58 59 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 60 pending on the resource when markPendingIO is called. */ 61 void setResource(GrGpuResource*, GrIOType); 62 63 private: 64 /** Called by owning GrProgramElement when the program element is first scheduled for 65 execution. It can only be called once. */ 66 void markPendingIO() const; 67 68 /** Called when the program element/draw state is no longer owned by GrOpList-client code. 69 This lets the cache know that the drawing code will no longer schedule additional reads or 70 writes to the resource using the program element or draw state. It can only be called once. 71 */ 72 void removeRef() const; 73 74 /** Called to indicate that the previous pending IO is complete. Useful when the owning object 75 still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously 76 pending executions have been complete. Can only be called if removeRef() was not previously 77 called. */ 78 void pendingIOComplete() const; 79 80 friend class GrResourceIOProcessor; 81 82 GrGpuResource* fResource; 83 mutable bool fOwnRef; 84 mutable bool fPendingIO; 85 GrIOType fIOType; 86 87 typedef SkNoncopyable INHERITED; 88 }; 89 90 /** 91 * Templated version of GrGpuResourceRef to enforce type safety. 92 */ 93 template <typename T> class GrTGpuResourceRef : public GrGpuResourceRef { 94 public: 95 GrTGpuResourceRef() {} 96 97 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 98 pending on the resource when markPendingIO is called. */ 99 GrTGpuResourceRef(T* resource, GrIOType ioType) : INHERITED(resource, ioType) {} 100 GrTGpuResourceRef(sk_sp<T> resource, GrIOType ioType) : INHERITED(resource, ioType) {} 101 102 T* get() const { return static_cast<T*>(this->getResource()); } 103 104 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 105 pending on the resource when markPendingIO is called. */ 106 void set(T* resource, GrIOType ioType) { this->setResource(resource, ioType); } 107 108 private: 109 typedef GrGpuResourceRef INHERITED; 110 }; 111 112 /** 113 * This is similar to GrTGpuResourceRef but can only be in the pending IO state. It never owns a 114 * ref. 115 */ 116 template <typename T, GrIOType IO_TYPE> class GrPendingIOResource : SkNoncopyable { 117 public: 118 GrPendingIOResource(T* resource = nullptr) : fResource(nullptr) { 119 this->reset(resource); 120 } 121 122 GrPendingIOResource(const GrPendingIOResource& that) 123 : GrPendingIOResource(that.get()) { 124 } 125 126 void reset(T* resource = nullptr) { 127 if (resource) { 128 switch (IO_TYPE) { 129 case kRead_GrIOType: 130 resource->addPendingRead(); 131 break; 132 case kWrite_GrIOType: 133 resource->addPendingWrite(); 134 break; 135 case kRW_GrIOType: 136 resource->addPendingRead(); 137 resource->addPendingWrite(); 138 break; 139 } 140 } 141 this->release(); 142 fResource = resource; 143 } 144 145 ~GrPendingIOResource() { 146 this->release(); 147 } 148 149 explicit operator bool() const { return SkToBool(fResource); } 150 151 bool operator==(const GrPendingIOResource& other) const { 152 return fResource == other.fResource; 153 } 154 155 T* get() const { return fResource; } 156 157 private: 158 void release() { 159 if (fResource) { 160 switch (IO_TYPE) { 161 case kRead_GrIOType: 162 fResource->completedRead(); 163 break; 164 case kWrite_GrIOType: 165 fResource->completedWrite(); 166 break; 167 case kRW_GrIOType: 168 fResource->completedRead(); 169 fResource->completedWrite(); 170 break; 171 } 172 } 173 } 174 175 T* fResource; 176 }; 177 178 #endif 179