| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #ifndef GrGpuResource_DEFINED | 8 #ifndef GrGpuResource_DEFINED |
| 9 #define GrGpuResource_DEFINED | 9 #define GrGpuResource_DEFINED |
| 10 | 10 |
| 11 #include "GrResourceKey.h" |
| 12 #include "GrTypesPriv.h" |
| 11 #include "SkInstCnt.h" | 13 #include "SkInstCnt.h" |
| 12 #include "SkTInternalLList.h" | 14 #include "SkTInternalLList.h" |
| 13 #include "GrResourceKey.h" | |
| 14 | 15 |
| 15 class GrResourceCacheEntry; | 16 class GrResourceCacheEntry; |
| 16 class GrResourceCache2; | 17 class GrResourceCache2; |
| 17 class GrGpu; | 18 class GrGpu; |
| 18 class GrContext; | 19 class GrContext; |
| 19 | 20 |
| 20 /** | 21 /** |
| 21 * Base class for GrGpuResource. Handles the various types of refs we need. Sepa
rated out as a base | 22 * Base class for GrGpuResource. Handles the various types of refs we need. Sepa
rated out as a base |
| 22 * class to isolate the ref-cnting behavior and provide friendship without expos
ing all of | 23 * class to isolate the ref-cnting behavior and provide friendship without expos
ing all of |
| 23 * GrGpuResource. | 24 * GrGpuResource. |
| 24 * | 25 * |
| 25 * Gpu resources can have three types of refs: | 26 * Gpu resources can have three types of refs: |
| 26 * 1) Normal ref (+ by ref(), - by unref()): These are used by code that is is
suing draw calls | 27 * 1) Normal ref (+ by ref(), - by unref()): These are used by code that is is
suing draw calls |
| 27 * that read and write the resource via GrDrawTarget and by any object that
must own a | 28 * 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-clien
t code. | 29 * GrGpuResource and is itself owned (directly or indirectly) by Skia-clien
t code. |
| 29 * 2) Pending read (+ by addPendingRead(), - by readCompleted()): GrContext ha
s scheduled a read | 30 * 2) Pending read (+ by addPendingRead(), - by completedRead()): GrContext ha
s scheduled a read |
| 30 * of the resource by the GPU as a result of a skia API call but hasn't exe
cuted it yet. | 31 * of the resource by the GPU as a result of a skia API call but hasn't exe
cuted it yet. |
| 31 * 3) Pending write (+ by addPendingWrite(), - by writeCompleted()): GrContext
has scheduled a | 32 * 3) Pending write (+ by addPendingWrite(), - by completedWrite()): 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 * write to the resource by the GPU as a result of a skia API call but hasn
't executed it yet. |
| 33 * | 34 * |
| 34 * The latter two ref types are private and intended only for Gr core code. | 35 * The latter two ref types are private and intended only for Gr core code. |
| 36 * |
| 37 * When an item is purgable DERIVED:notifyIsPurgable() will be called (static po
ly morphism using |
| 38 * CRTP). GrIORef and GrGpuResource are separate classes for organizational reas
ons and to be |
| 39 * able to give access via friendship to only the functions related to pending I
O operations. |
| 35 */ | 40 */ |
| 36 class GrIORef : public SkNoncopyable { | 41 template <typename DERIVED> class GrIORef : public SkNoncopyable { |
| 37 public: | 42 public: |
| 38 SK_DECLARE_INST_COUNT_ROOT(GrIORef) | 43 SK_DECLARE_INST_COUNT_ROOT(GrIORef) |
| 39 | |
| 40 enum IOType { | |
| 41 kRead_IOType, | |
| 42 kWrite_IOType, | |
| 43 kRW_IOType | |
| 44 }; | |
| 45 | |
| 46 virtual ~GrIORef(); | 44 virtual ~GrIORef(); |
| 47 | 45 |
| 48 // Some of the signatures are written to mirror SkRefCnt so that GrGpuResour
ce can work with | 46 // Some of the signatures are written to mirror SkRefCnt so that GrGpuResour
ce can work with |
| 49 // templated helper classes (e.g. SkAutoTUnref). However, we have different
categories of | 47 // 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 GrCache
able objects are | 48 // refs (e.g. pending reads). We also don't require thread safety as GrCache
able objects are |
| 51 // not intended to cross thread boundaries. | 49 // 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 { | 50 void ref() const { |
| 51 this->validate(); |
| 55 ++fRefCnt; | 52 ++fRefCnt; |
| 56 // pre-validate once internal_dispose is removed (and therefore 0 ref cn
t is not allowed). | |
| 57 this->validate(); | |
| 58 } | 53 } |
| 59 | 54 |
| 60 void unref() const { | 55 void unref() const { |
| 61 this->validate(); | 56 this->validate(); |
| 62 --fRefCnt; | 57 --fRefCnt; |
| 63 if (0 == fRefCnt && 0 == fPendingReads && 0 == fPendingWrites) { | 58 this->didUnref(); |
| 64 this->internal_dispose(); | |
| 65 } | |
| 66 } | 59 } |
| 67 | 60 |
| 68 virtual void internal_dispose() const { SkDELETE(this); } | 61 bool isPurgable() const { return this->reffedOnlyByCache() && !this->interna
lHasPendingIO(); } |
| 69 | 62 bool reffedOnlyByCache() const { return 1 == fRefCnt; } |
| 70 /** This is exists to service the old mechanism for recycling scratch textur
es. It will | |
| 71 be removed soon. */ | |
| 72 bool unique() const { return 1 == (fRefCnt + fPendingReads + fPendingWrites)
; } | |
| 73 | 63 |
| 74 void validate() const { | 64 void validate() const { |
| 75 #ifdef SK_DEBUG | 65 #ifdef SK_DEBUG |
| 76 SkASSERT(fRefCnt >= 0); | 66 SkASSERT(fRefCnt >= 0); |
| 77 SkASSERT(fPendingReads >= 0); | 67 SkASSERT(fPendingReads >= 0); |
| 78 SkASSERT(fPendingWrites >= 0); | 68 SkASSERT(fPendingWrites >= 0); |
| 79 SkASSERT(fRefCnt + fPendingReads + fPendingWrites > 0); | 69 SkASSERT(fRefCnt + fPendingReads + fPendingWrites > 0); |
| 80 #endif | 70 #endif |
| 81 } | 71 } |
| 82 | 72 |
| 83 | |
| 84 protected: | 73 protected: |
| 85 GrIORef() : fRefCnt(1), fPendingReads(0), fPendingWrites(0) {} | 74 GrIORef() : fRefCnt(1), fPendingReads(0), fPendingWrites(0), fIsScratch(kNo_
IsScratch) { } |
| 86 | 75 |
| 87 bool internalHasPendingRead() const { return SkToBool(fPendingReads); } | 76 bool internalHasPendingRead() const { return SkToBool(fPendingReads); } |
| 88 bool internalHasPendingWrite() const { return SkToBool(fPendingWrites); } | 77 bool internalHasPendingWrite() const { return SkToBool(fPendingWrites); } |
| 89 bool internalHasPendingIO() const { return SkToBool(fPendingWrites | fPendin
gReads); } | 78 bool internalHasPendingIO() const { return SkToBool(fPendingWrites | fPendin
gReads); } |
| 90 | 79 |
| 91 private: | 80 private: |
| 92 void addPendingRead() const { | 81 void addPendingRead() const { |
| 93 this->validate(); | 82 this->validate(); |
| 94 ++fPendingReads; | 83 ++fPendingReads; |
| 95 } | 84 } |
| 96 | 85 |
| 97 void completedRead() const { | 86 void completedRead() const { |
| 98 this->validate(); | 87 this->validate(); |
| 99 --fPendingReads; | 88 --fPendingReads; |
| 100 if (0 == fRefCnt && 0 == fPendingReads && 0 == fPendingWrites) { | 89 this->didUnref(); |
| 101 this->internal_dispose(); | |
| 102 } | |
| 103 } | 90 } |
| 104 | 91 |
| 105 void addPendingWrite() const { | 92 void addPendingWrite() const { |
| 106 this->validate(); | 93 this->validate(); |
| 107 ++fPendingWrites; | 94 ++fPendingWrites; |
| 108 } | 95 } |
| 109 | 96 |
| 110 void completedWrite() const { | 97 void completedWrite() const { |
| 111 this->validate(); | 98 this->validate(); |
| 112 --fPendingWrites; | 99 --fPendingWrites; |
| 113 if (0 == fRefCnt && 0 == fPendingReads && 0 == fPendingWrites) { | 100 this->didUnref(); |
| 114 this->internal_dispose(); | 101 } |
| 102 |
| 103 private: |
| 104 void didUnref() const { |
| 105 if (0 == fPendingReads && 0 == fPendingWrites) { |
| 106 if (0 == fRefCnt) { |
| 107 SkDELETE(this); |
| 108 } else if (1 == fRefCnt) { |
| 109 // The one ref is the cache's |
| 110 static_cast<const DERIVED*>(this)->notifyIsPurgable(); |
| 111 } |
| 115 } | 112 } |
| 116 } | 113 } |
| 117 | 114 |
| 118 private: | |
| 119 mutable int32_t fRefCnt; | 115 mutable int32_t fRefCnt; |
| 120 mutable int32_t fPendingReads; | 116 mutable int32_t fPendingReads; |
| 121 mutable int32_t fPendingWrites; | 117 mutable int32_t fPendingWrites; |
| 122 | 118 |
| 123 // This class is used to manage conversion of refs to pending reads/writes. | 119 // This class is used to manage conversion of refs to pending reads/writes. |
| 124 friend class GrGpuResourceRef; | 120 friend class GrGpuResourceRef; |
| 125 template <typename, IOType> friend class GrPendingIOResource; | 121 |
| 122 // This is temporary until GrResourceCache is fully replaced by GrResourceCa
che2. |
| 123 enum IsScratch { |
| 124 kNo_IsScratch, |
| 125 kYes_IsScratch |
| 126 } fIsScratch; |
| 127 |
| 128 friend class GrContext; // to set the above field. |
| 129 friend class GrResourceCache; // to check the above field. |
| 130 friend class GrResourceCache2; // to check the above field. |
| 131 |
| 132 template <typename, GrIOType> friend class GrPendingIOResource; |
| 126 }; | 133 }; |
| 127 | 134 |
| 128 /** | 135 /** |
| 129 * Base class for objects that can be kept in the GrResourceCache. | 136 * Base class for objects that can be kept in the GrResourceCache. |
| 130 */ | 137 */ |
| 131 class GrGpuResource : public GrIORef { | 138 class GrGpuResource : public GrIORef<GrGpuResource> { |
| 132 public: | 139 public: |
| 133 SK_DECLARE_INST_COUNT(GrGpuResource) | 140 SK_DECLARE_INST_COUNT(GrGpuResource) |
| 134 | 141 |
| 135 /** | 142 /** |
| 136 * Frees the object in the underlying 3D API. It must be safe to call this | 143 * Frees the object in the underlying 3D API. It must be safe to call this |
| 137 * when the object has been previously abandoned. | 144 * when the object has been previously abandoned. |
| 138 */ | 145 */ |
| 139 void release(); | 146 void release(); |
| 140 | 147 |
| 141 /** | 148 /** |
| (...skipping 26 matching lines...) Expand all Loading... |
| 168 /** | 175 /** |
| 169 * Retrieves the amount of GPU memory used by this resource in bytes. It is | 176 * 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 | 177 * approximate since we aren't aware of additional padding or copies made |
| 171 * by the driver. | 178 * by the driver. |
| 172 * | 179 * |
| 173 * @return the amount of GPU memory used in bytes | 180 * @return the amount of GPU memory used in bytes |
| 174 */ | 181 */ |
| 175 virtual size_t gpuMemorySize() const = 0; | 182 virtual size_t gpuMemorySize() const = 0; |
| 176 | 183 |
| 177 void setCacheEntry(GrResourceCacheEntry* cacheEntry) { fCacheEntry = cacheEn
try; } | 184 void setCacheEntry(GrResourceCacheEntry* cacheEntry) { fCacheEntry = cacheEn
try; } |
| 178 GrResourceCacheEntry* getCacheEntry() { return fCacheEntry; } | 185 GrResourceCacheEntry* getCacheEntry() const { return fCacheEntry; } |
| 179 | 186 |
| 180 /** | 187 /** |
| 181 * If this resource can be used as a scratch resource this returns a valid | 188 * 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. | 189 * scratch key. Otherwise it returns a key for which isNullScratch is true. |
| 183 */ | 190 */ |
| 184 const GrResourceKey& getScratchKey() const { return fScratchKey; } | 191 const GrResourceKey& getScratchKey() const { return fScratchKey; } |
| 185 | 192 |
| 186 /** | 193 /** |
| 187 * Gets an id that is unique for this GrGpuResource object. It is static in
that it does | 194 * 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 wil
l never return | 195 * not change when the content of the GrGpuResource object changes. This wil
l never return |
| (...skipping 28 matching lines...) Expand all Loading... |
| 217 */ | 224 */ |
| 218 void didChangeGpuMemorySize() const; | 225 void didChangeGpuMemorySize() const; |
| 219 | 226 |
| 220 /** | 227 /** |
| 221 * Optionally called by the GrGpuResource subclass if the resource can be us
ed as scratch. | 228 * Optionally called by the GrGpuResource subclass if the resource can be us
ed as scratch. |
| 222 * By default resources are not usable as scratch. This should only be calle
d once. | 229 * By default resources are not usable as scratch. This should only be calle
d once. |
| 223 **/ | 230 **/ |
| 224 void setScratchKey(const GrResourceKey& scratchKey); | 231 void setScratchKey(const GrResourceKey& scratchKey); |
| 225 | 232 |
| 226 private: | 233 private: |
| 234 void notifyIsPurgable() const; |
| 235 |
| 227 #ifdef SK_DEBUG | 236 #ifdef SK_DEBUG |
| 228 friend class GrGpu; // for assert in GrGpu to access getGpu | 237 friend class GrGpu; // for assert in GrGpu to access getGpu |
| 229 #endif | 238 #endif |
| 230 | 239 |
| 231 static uint32_t CreateUniqueID(); | 240 static uint32_t CreateUniqueID(); |
| 232 | 241 |
| 233 // We're in an internal doubly linked list owned by GrResourceCache2 | 242 // We're in an internal doubly linked list owned by GrResourceCache2 |
| 234 SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrGpuResource); | 243 SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrGpuResource); |
| 235 | 244 |
| 236 // This is not ref'ed but abandon() or release() will be called before the G
rGpu object | 245 // This is not ref'ed but abandon() or release() will be called before the G
rGpu object |
| 237 // is destroyed. Those calls set will this to NULL. | 246 // is destroyed. Those calls set will this to NULL. |
| 238 GrGpu* fGpu; | 247 GrGpu* fGpu; |
| 239 | 248 |
| 240 enum Flags { | 249 enum Flags { |
| 241 /** | 250 /** |
| 242 * This object wraps a GPU object given to us by the user. | 251 * 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 | 252 * Lifetime management is left up to the user (i.e., we will not |
| 244 * free it). | 253 * free it). |
| 245 */ | 254 */ |
| 246 kWrapped_FlagBit = 0x1, | 255 kWrapped_FlagBit = 0x1, |
| 247 }; | 256 }; |
| 248 | 257 |
| 249 uint32_t fFlags; | 258 uint32_t fFlags; |
| 250 | 259 |
| 251 GrResourceCacheEntry* fCacheEntry; // NULL if not in cache | 260 GrResourceCacheEntry* fCacheEntry; // NULL if not in cache |
| 252 const uint32_t fUniqueID; | 261 const uint32_t fUniqueID; |
| 253 | 262 |
| 254 GrResourceKey fScratchKey; | 263 GrResourceKey fScratchKey; |
| 255 | 264 |
| 256 typedef GrIORef INHERITED; | 265 typedef GrIORef<GrGpuResource> INHERITED; |
| 266 friend class GrIORef<GrGpuResource>; // to access notifyIsPurgable. |
| 257 }; | 267 }; |
| 258 | 268 |
| 259 #endif | 269 #endif |
| OLD | NEW |