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 sk_sp, 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 getResource()41 GrGpuResource* getResource() const { return fResource; } 42 43 /** Does this object own a pending read or write on the resource it is wrapping. */ ownsPendingIO()44 bool ownsPendingIO() const { return fPendingIO; } 45 46 /** What type of IO does this represent? This is independent of whether a normal ref or a 47 pending IO is currently held. */ ioType()48 GrIOType ioType() const { return fIOType; } 49 50 /** Shortcut for calling setResource() with NULL. It cannot be called after markingPendingIO 51 is called. */ 52 void reset(); 53 54 protected: 55 GrGpuResourceRef(); 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 GrGpuResourceRef(GrGpuResource*, GrIOType); 60 61 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 62 pending on the resource when markPendingIO is called. */ 63 void setResource(GrGpuResource*, GrIOType); 64 65 private: 66 /** Called by owning GrProgramElement when the program element is first scheduled for 67 execution. It can only be called once. */ 68 void markPendingIO() const; 69 70 /** Called when the program element/draw state is no longer owned by GrOpList-client code. 71 This lets the cache know that the drawing code will no longer schedule additional reads or 72 writes to the resource using the program element or draw state. It can only be called once. 73 */ 74 void removeRef() const; 75 76 /** Called to indicate that the previous pending IO is complete. Useful when the owning object 77 still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously 78 pending executions have been complete. Can only be called if removeRef() was not previously 79 called. */ 80 void pendingIOComplete() const; 81 82 friend class GrProcessor; 83 84 GrGpuResource* fResource; 85 mutable bool fOwnRef; 86 mutable bool fPendingIO; 87 GrIOType fIOType; 88 89 typedef SkNoncopyable INHERITED; 90 }; 91 92 /** 93 * Templated version of GrGpuResourceRef to enforce type safety. 94 */ 95 template <typename T> class GrTGpuResourceRef : public GrGpuResourceRef { 96 public: GrTGpuResourceRef()97 GrTGpuResourceRef() {} 98 99 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 100 pending on the resource when markPendingIO is called. */ GrTGpuResourceRef(T * resource,GrIOType ioType)101 GrTGpuResourceRef(T* resource, GrIOType ioType) : INHERITED(resource, ioType) { } 102 get()103 T* get() const { return static_cast<T*>(this->getResource()); } 104 105 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 106 pending on the resource when markPendingIO is called. */ set(T * resource,GrIOType ioType)107 void set(T* resource, GrIOType ioType) { this->setResource(resource, ioType); } 108 109 private: 110 typedef GrGpuResourceRef INHERITED; 111 }; 112 113 // Specializations for GrTexture and GrRenderTarget because they use virtual inheritance. 114 template<> class GrTGpuResourceRef<GrTexture> : public GrGpuResourceRef { 115 public: GrTGpuResourceRef()116 GrTGpuResourceRef() {} 117 GrTGpuResourceRef(GrTexture * texture,GrIOType ioType)118 GrTGpuResourceRef(GrTexture* texture, GrIOType ioType) : INHERITED(texture, ioType) { } 119 get()120 GrTexture* get() const { 121 GrSurface* surface = static_cast<GrSurface*>(this->getResource()); 122 if (surface) { 123 return surface->asTexture(); 124 } else { 125 return NULL; 126 } 127 } 128 set(GrTexture * texture,GrIOType ioType)129 void set(GrTexture* texture, GrIOType ioType) { this->setResource(texture, ioType); } 130 131 private: 132 typedef GrGpuResourceRef INHERITED; 133 }; 134 135 template<> class GrTGpuResourceRef<GrRenderTarget> : public GrGpuResourceRef { 136 public: GrTGpuResourceRef()137 GrTGpuResourceRef() {} 138 GrTGpuResourceRef(GrRenderTarget * rt,GrIOType ioType)139 GrTGpuResourceRef(GrRenderTarget* rt, GrIOType ioType) : INHERITED(rt, ioType) { } 140 get()141 GrRenderTarget* get() const { 142 GrSurface* surface = static_cast<GrSurface*>(this->getResource()); 143 if (surface) { 144 return surface->asRenderTarget(); 145 } else { 146 return NULL; 147 } 148 } 149 set(GrRenderTarget * rt,GrIOType ioType)150 void set(GrRenderTarget* rt, GrIOType ioType) { this->setResource(rt, ioType); } 151 152 private: 153 typedef GrGpuResourceRef INHERITED; 154 }; 155 156 /** 157 * This is similar to GrTGpuResourceRef but can only be in the pending IO state. It never owns a 158 * ref. 159 */ 160 template <typename T, GrIOType IO_TYPE> class GrPendingIOResource : SkNoncopyable { 161 public: fResource(NULL)162 GrPendingIOResource(T* resource = NULL) : fResource(NULL) { 163 this->reset(resource); 164 } 165 reset(T * resource)166 void reset(T* resource) { 167 if (resource) { 168 switch (IO_TYPE) { 169 case kRead_GrIOType: 170 resource->addPendingRead(); 171 break; 172 case kWrite_GrIOType: 173 resource->addPendingWrite(); 174 break; 175 case kRW_GrIOType: 176 resource->addPendingRead(); 177 resource->addPendingWrite(); 178 break; 179 } 180 } 181 this->release(); 182 fResource = resource; 183 } 184 ~GrPendingIOResource()185 ~GrPendingIOResource() { 186 this->release(); 187 } 188 189 explicit operator bool() const { return SkToBool(fResource); } 190 191 bool operator==(const GrPendingIOResource& other) const { 192 return fResource == other.fResource; 193 } 194 get()195 T* get() const { return fResource; } 196 197 private: release()198 void release() { 199 if (fResource) { 200 switch (IO_TYPE) { 201 case kRead_GrIOType: 202 fResource->completedRead(); 203 break; 204 case kWrite_GrIOType: 205 fResource->completedWrite(); 206 break; 207 case kRW_GrIOType: 208 fResource->completedRead(); 209 fResource->completedWrite(); 210 break; 211 } 212 } 213 } 214 215 T* fResource; 216 }; 217 #endif 218