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 |