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