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 GrGpuResource_DEFINED 9 #define GrGpuResource_DEFINED 10 11 #include "SkInstCnt.h" 12 #include "SkTInternalLList.h" 13 #include "GrResourceKey.h" 14 15 class GrResourceCacheEntry; 16 class GrResourceCache2; 17 class GrGpu; 18 class GrContext; 19 20 /** 21 * Base class for GrGpuResource. Handles the various types of refs we need. Separated out as a base 22 * class to isolate the ref-cnting behavior and provide friendship without exposing all of 23 * GrGpuResource. 24 * 25 * Gpu resources can have three types of refs: 26 * 1) Normal ref (+ by ref(), - by unref()): These are used by code that is issuing draw calls 27 * that read and write the resource via GrDrawTarget and by any object that must own a 28 * GrGpuResource and is itself owned (directly or indirectly) by Skia-client code. 29 * 2) Pending read (+ by addPendingRead(), - by readCompleted()): GrContext has scheduled a read 30 * of the resource by the GPU as a result of a skia API call but hasn't executed it yet. 31 * 3) Pending write (+ by addPendingWrite(), - by writeCompleted()): GrContext has scheduled a 32 * write to the resource by the GPU as a result of a skia API call but hasn't executed it yet. 33 * 34 * The latter two ref types are private and intended only for Gr core code. 35 */ 36 class GrIORef : public SkNoncopyable { 37 public: 38 SK_DECLARE_INST_COUNT_ROOT(GrIORef) 39 40 enum IOType { 41 kRead_IOType, 42 kWrite_IOType, 43 kRW_IOType 44 }; 45 46 virtual ~GrIORef(); 47 48 // Some of the signatures are written to mirror SkRefCnt so that GrGpuResource can work with 49 // templated helper classes (e.g. SkAutoTUnref). However, we have different categories of 50 // refs (e.g. pending reads). We also don't require thread safety as GrCacheable objects are 51 // not intended to cross thread boundaries. 52 // internal_dispose() exists because of GrTexture's reliance on it. It will be removed 53 // soon. 54 void ref() const { 55 ++fRefCnt; 56 // pre-validate once internal_dispose is removed (and therefore 0 ref cnt is not allowed). 57 this->validate(); 58 } 59 60 void unref() const { 61 this->validate(); 62 --fRefCnt; 63 if (0 == fRefCnt && 0 == fPendingReads && 0 == fPendingWrites) { 64 this->internal_dispose(); 65 } 66 } 67 68 virtual void internal_dispose() const { SkDELETE(this); } 69 70 /** This is exists to service the old mechanism for recycling scratch textures. It will 71 be removed soon. */ 72 bool unique() const { return 1 == (fRefCnt + fPendingReads + fPendingWrites); } 73 74 void validate() const { 75 #ifdef SK_DEBUG 76 SkASSERT(fRefCnt >= 0); 77 SkASSERT(fPendingReads >= 0); 78 SkASSERT(fPendingWrites >= 0); 79 SkASSERT(fRefCnt + fPendingReads + fPendingWrites > 0); 80 #endif 81 } 82 83 84 protected: 85 GrIORef() : fRefCnt(1), fPendingReads(0), fPendingWrites(0) {} 86 87 bool internalHasPendingRead() const { return SkToBool(fPendingReads); } 88 bool internalHasPendingWrite() const { return SkToBool(fPendingWrites); } 89 bool internalHasPendingIO() const { return SkToBool(fPendingWrites | fPendingReads); } 90 91 private: 92 void addPendingRead() const { 93 this->validate(); 94 ++fPendingReads; 95 } 96 97 void completedRead() const { 98 this->validate(); 99 --fPendingReads; 100 if (0 == fRefCnt && 0 == fPendingReads && 0 == fPendingWrites) { 101 this->internal_dispose(); 102 } 103 } 104 105 void addPendingWrite() const { 106 this->validate(); 107 ++fPendingWrites; 108 } 109 110 void completedWrite() const { 111 this->validate(); 112 --fPendingWrites; 113 if (0 == fRefCnt && 0 == fPendingReads && 0 == fPendingWrites) { 114 this->internal_dispose(); 115 } 116 } 117 118 private: 119 mutable int32_t fRefCnt; 120 mutable int32_t fPendingReads; 121 mutable int32_t fPendingWrites; 122 123 // This class is used to manage conversion of refs to pending reads/writes. 124 friend class GrGpuResourceRef; 125 template <typename, IOType> friend class GrPendingIOResource; 126 }; 127 128 /** 129 * Base class for objects that can be kept in the GrResourceCache. 130 */ 131 class GrGpuResource : public GrIORef { 132 public: 133 SK_DECLARE_INST_COUNT(GrGpuResource) 134 135 /** 136 * Frees the object in the underlying 3D API. It must be safe to call this 137 * when the object has been previously abandoned. 138 */ 139 void release(); 140 141 /** 142 * Removes references to objects in the underlying 3D API without freeing 143 * them. Used when the API context has been torn down before the GrContext. 144 */ 145 void abandon(); 146 147 /** 148 * Tests whether a object has been abandoned or released. All objects will 149 * be in this state after their creating GrContext is destroyed or has 150 * contextLost called. It's up to the client to test wasDestroyed() before 151 * attempting to use an object if it holds refs on objects across 152 * ~GrContext, freeResources with the force flag, or contextLost. 153 * 154 * @return true if the object has been released or abandoned, 155 * false otherwise. 156 */ 157 bool wasDestroyed() const { return NULL == fGpu; } 158 159 /** 160 * Retrieves the context that owns the object. Note that it is possible for 161 * this to return NULL. When objects have been release()ed or abandon()ed 162 * they no longer have an owning context. Destroying a GrContext 163 * automatically releases all its resources. 164 */ 165 const GrContext* getContext() const; 166 GrContext* getContext(); 167 168 /** 169 * Retrieves the amount of GPU memory used by this resource in bytes. It is 170 * approximate since we aren't aware of additional padding or copies made 171 * by the driver. 172 * 173 * @return the amount of GPU memory used in bytes 174 */ 175 virtual size_t gpuMemorySize() const = 0; 176 177 void setCacheEntry(GrResourceCacheEntry* cacheEntry) { fCacheEntry = cacheEntry; } 178 GrResourceCacheEntry* getCacheEntry() { return fCacheEntry; } 179 180 /** 181 * If this resource can be used as a scratch resource this returns a valid 182 * scratch key. Otherwise it returns a key for which isNullScratch is true. 183 */ 184 const GrResourceKey& getScratchKey() const { return fScratchKey; } 185 186 /** 187 * Gets an id that is unique for this GrGpuResource object. It is static in that it does 188 * not change when the content of the GrGpuResource object changes. This will never return 189 * 0. 190 */ 191 uint32_t getUniqueID() const { return fUniqueID; } 192 193 protected: 194 // This must be called by every GrGpuObject. It should be called once the object is fully 195 // initialized (i.e. not in a base class constructor). 196 void registerWithCache(); 197 198 GrGpuResource(GrGpu*, bool isWrapped); 199 virtual ~GrGpuResource(); 200 201 bool isInCache() const { return SkToBool(fCacheEntry); } 202 203 GrGpu* getGpu() const { return fGpu; } 204 205 // Derived classes should always call their parent class' onRelease 206 // and onAbandon methods in their overrides. 207 virtual void onRelease() {}; 208 virtual void onAbandon() {}; 209 210 bool isWrapped() const { return kWrapped_FlagBit & fFlags; } 211 212 /** 213 * This entry point should be called whenever gpuMemorySize() begins 214 * reporting a different size. If the object is in the cache, it will call 215 * gpuMemorySize() immediately and pass the new size on to the resource 216 * cache. 217 */ 218 void didChangeGpuMemorySize() const; 219 220 /** 221 * Optionally called by the GrGpuResource subclass if the resource can be used as scratch. 222 * By default resources are not usable as scratch. This should only be called once. 223 **/ 224 void setScratchKey(const GrResourceKey& scratchKey); 225 226 private: 227 #ifdef SK_DEBUG 228 friend class GrGpu; // for assert in GrGpu to access getGpu 229 #endif 230 231 static uint32_t CreateUniqueID(); 232 233 // We're in an internal doubly linked list owned by GrResourceCache2 234 SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrGpuResource); 235 236 // This is not ref'ed but abandon() or release() will be called before the GrGpu object 237 // is destroyed. Those calls set will this to NULL. 238 GrGpu* fGpu; 239 240 enum Flags { 241 /** 242 * This object wraps a GPU object given to us by the user. 243 * Lifetime management is left up to the user (i.e., we will not 244 * free it). 245 */ 246 kWrapped_FlagBit = 0x1, 247 }; 248 249 uint32_t fFlags; 250 251 GrResourceCacheEntry* fCacheEntry; // NULL if not in cache 252 const uint32_t fUniqueID; 253 254 GrResourceKey fScratchKey; 255 256 typedef GrIORef INHERITED; 257 }; 258 259 #endif 260