OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 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 GrEffect_DEFINED | 8 #ifndef GrEffect_DEFINED |
9 #define GrEffect_DEFINED | 9 #define GrEffect_DEFINED |
10 | 10 |
11 #include "GrColor.h" | 11 #include "GrColor.h" |
12 #include "GrEffectUnitTest.h" | 12 #include "GrEffectUnitTest.h" |
13 #include "GrTexture.h" | 13 #include "GrTexture.h" |
14 #include "GrTextureAccess.h" | 14 #include "GrTextureAccess.h" |
15 #include "GrTypesPriv.h" | 15 #include "GrTypesPriv.h" |
16 | 16 |
17 class GrBackendEffectFactory; | 17 class GrBackendEffectFactory; |
18 class GrContext; | 18 class GrContext; |
19 class GrCoordTransform; | 19 class GrCoordTransform; |
20 class GrEffect; | 20 class GrEffect; |
21 class GrVertexEffect; | 21 class GrVertexEffect; |
22 class SkString; | 22 class SkString; |
23 | 23 |
24 /** | |
25 * A Wrapper class for GrEffect. Its ref-count will track owners that may use ef
fects to enqueue | |
26 * new draw operations separately from ownership within a deferred drawing queue
. When the | |
27 * GrEffectRef ref count reaches zero the scratch GrResources owned by the effec
t can be recycled | |
28 * in service of later draws. However, the deferred draw queue may still own dir
ect references to | |
29 * the underlying GrEffect. | |
30 * | |
31 * GrEffectRefs created by new are placed in a per-thread managed pool. The pool
is destroyed when | |
32 * the thread ends. Therefore, all dynamically allocated GrEffectRefs must be un
reffed before thread | |
33 * termination. | |
34 */ | |
35 class GrEffectRef : public SkRefCnt { | |
36 public: | |
37 SK_DECLARE_INST_COUNT(GrEffectRef); | |
38 virtual ~GrEffectRef(); | |
39 | |
40 GrEffect* get() { return fEffect; } | |
41 const GrEffect* get() const { return fEffect; } | |
42 | |
43 const GrEffect* operator-> () { return fEffect; } | |
44 const GrEffect* operator-> () const { return fEffect; } | |
45 | |
46 void* operator new(size_t size); | |
47 void operator delete(void* target); | |
48 | |
49 void* operator new(size_t size, void* placement) { | |
50 return ::operator new(size, placement); | |
51 } | |
52 void operator delete(void* target, void* placement) { | |
53 ::operator delete(target, placement); | |
54 } | |
55 | |
56 private: | |
57 friend class GrEffect; // to construct these | |
58 | |
59 explicit GrEffectRef(GrEffect* effect); | |
60 | |
61 GrEffect* fEffect; | |
62 | |
63 typedef SkRefCnt INHERITED; | |
64 }; | |
65 | |
66 /** Provides custom vertex shader, fragment shader, uniform data for a particula
r stage of the | 24 /** Provides custom vertex shader, fragment shader, uniform data for a particula
r stage of the |
67 Ganesh shading pipeline. | 25 Ganesh shading pipeline. |
68 Subclasses must have a function that produces a human-readable name: | 26 Subclasses must have a function that produces a human-readable name: |
69 static const char* Name(); | 27 static const char* Name(); |
70 GrEffect objects *must* be immutable: after being constructed, their fields
may not change. | 28 GrEffect objects *must* be immutable: after being constructed, their fields
may not change. |
71 | 29 |
72 GrEffect subclass objects should be created by factory functions that return
GrEffectRef. | 30 Dynamically allocated GrEffects are managed by a per-thread memory pool. The
ref count of an |
73 There is no public way to wrap a GrEffect in a GrEffectRef. Thus, a factory
should be a static | 31 effect must reach 0 before the thread terminates and the pool is destroyed.
To create a static |
74 member function of a GrEffect subclass. | 32 effect use the macro GR_CREATE_STATIC_EFFECT declared below. |
75 | |
76 Because almost no code should ever handle a GrEffect directly outside of a G
rEffectRef, we | |
77 privately inherit from SkRefCnt to help prevent accidental direct ref'ing/un
ref'ing of effects. | |
78 | |
79 Dynamically allocated GrEffects and their corresponding GrEffectRefs are man
aged by a per-thread | |
80 memory pool. The ref count of an effect must reach 0 before the thread termi
nates and the pool | |
81 is destroyed. To create a static effect use the macro GR_CREATE_STATIC_EFFEC
T declared below. | |
82 */ | 33 */ |
83 class GrEffect : private SkRefCnt { | 34 class GrEffect : public SkRefCnt { |
84 public: | 35 public: |
85 SK_DECLARE_INST_COUNT(GrEffect) | 36 SK_DECLARE_INST_COUNT(GrEffect) |
86 | 37 |
87 virtual ~GrEffect(); | 38 virtual ~GrEffect(); |
88 | 39 |
89 /** | 40 /** |
90 * This function is used to perform optimizations. When called the color and
validFlags params | 41 * This function is used to perform optimizations. When called the color and
validFlags params |
91 * indicate whether the input components to this effect in the FS will have
known values. | 42 * indicate whether the input components to this effect in the FS will have
known values. |
92 * validFlags is a bitfield of GrColorComponentFlags. The function updates b
oth params to | 43 * validFlags is a bitfield of GrColorComponentFlags. The function updates b
oth params to |
93 * indicate known values of its output. A component of the color param only
has meaning if the | 44 * indicate known values of its output. A component of the color param only
has meaning if the |
(...skipping 23 matching lines...) Expand all Loading... |
117 | 68 |
118 /** Returns true if this and other effect conservatively draw identically. I
t can only return | 69 /** Returns true if this and other effect conservatively draw identically. I
t can only return |
119 true when the two effects are of the same subclass (i.e. they return the
same object from | 70 true when the two effects are of the same subclass (i.e. they return the
same object from |
120 from getFactory()). | 71 from getFactory()). |
121 | 72 |
122 A return value of true from isEqual() should not be used to test whether
the effects would | 73 A return value of true from isEqual() should not be used to test whether
the effects would |
123 generate the same shader code. To test for identical code generation use
the EffectKey | 74 generate the same shader code. To test for identical code generation use
the EffectKey |
124 computed by the GrBackendEffectFactory: | 75 computed by the GrBackendEffectFactory: |
125 effectA.getFactory().glEffectKey(effectA) == effectB.getFactory().gl
EffectKey(effectB). | 76 effectA.getFactory().glEffectKey(effectA) == effectB.getFactory().gl
EffectKey(effectB). |
126 */ | 77 */ |
127 bool isEqual(const GrEffectRef& other) const { | 78 bool isEqual(const GrEffect& other) const { |
128 return this->isEqual(*other.get()); | 79 if (&this->getFactory() != &other.getFactory()) { |
| 80 return false; |
| 81 } |
| 82 bool result = this->onIsEqual(other); |
| 83 #ifdef SK_DEBUG |
| 84 if (result) { |
| 85 this->assertEquality(other); |
| 86 } |
| 87 #endif |
| 88 return result; |
129 } | 89 } |
130 | 90 |
131 /** Human-meaningful string to identify this effect; may be embedded | 91 /** Human-meaningful string to identify this effect; may be embedded |
132 in generated shader code. */ | 92 in generated shader code. */ |
133 const char* name() const; | 93 const char* name() const; |
134 | 94 |
135 int numTransforms() const { return fCoordTransforms.count(); } | 95 int numTransforms() const { return fCoordTransforms.count(); } |
136 | 96 |
137 /** Returns the coordinate transformation at index. index must be valid acco
rding to | 97 /** Returns the coordinate transformation at index. index must be valid acco
rding to |
138 numTransforms(). */ | 98 numTransforms(). */ |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 void* operator new(size_t size); | 138 void* operator new(size_t size); |
179 void operator delete(void* target); | 139 void operator delete(void* target); |
180 | 140 |
181 void* operator new(size_t size, void* placement) { | 141 void* operator new(size_t size, void* placement) { |
182 return ::operator new(size, placement); | 142 return ::operator new(size, placement); |
183 } | 143 } |
184 void operator delete(void* target, void* placement) { | 144 void operator delete(void* target, void* placement) { |
185 ::operator delete(target, placement); | 145 ::operator delete(target, placement); |
186 } | 146 } |
187 | 147 |
188 /** These functions are used when recording effects into a deferred drawing
queue. The inc call | |
189 keeps the effect alive outside of GrEffectRef while allowing any resourc
es owned by the | |
190 effect to be returned to the cache for reuse. The dec call must balance
the inc call. */ | |
191 void incDeferredRefCounts() const { | |
192 this->ref(); | |
193 int count = fTextureAccesses.count(); | |
194 for (int t = 0; t < count; ++t) { | |
195 fTextureAccesses[t]->getTexture()->incDeferredRefCount(); | |
196 } | |
197 } | |
198 void decDeferredRefCounts() const { | |
199 int count = fTextureAccesses.count(); | |
200 for (int t = 0; t < count; ++t) { | |
201 fTextureAccesses[t]->getTexture()->decDeferredRefCount(); | |
202 } | |
203 this->unref(); | |
204 } | |
205 | |
206 protected: | 148 protected: |
207 /** | 149 /** |
208 * Subclasses call this from their constructor to register coordinate transf
ormations. The | 150 * Subclasses call this from their constructor to register coordinate transf
ormations. The |
209 * effect subclass manages the lifetime of the transformations (this functio
n only stores a | 151 * effect subclass manages the lifetime of the transformations (this functio
n only stores a |
210 * pointer). The GrCoordTransform is typically a member field of the GrEffec
t subclass. When the | 152 * pointer). The GrCoordTransform is typically a member field of the GrEffec
t subclass. When the |
211 * matrix has perspective, the transformed coordinates will have 3 component
s. Otherwise they'll | 153 * matrix has perspective, the transformed coordinates will have 3 component
s. Otherwise they'll |
212 * have 2. This must only be called from the constructor because GrEffects a
re immutable. | 154 * have 2. This must only be called from the constructor because GrEffects a
re immutable. |
213 */ | 155 */ |
214 void addCoordTransform(const GrCoordTransform* coordTransform); | 156 void addCoordTransform(const GrCoordTransform* coordTransform); |
215 | 157 |
216 /** | 158 /** |
217 * Subclasses call this from their constructor to register GrTextureAccesses
. The effect | 159 * Subclasses call this from their constructor to register GrTextureAccesses
. The effect |
218 * subclass manages the lifetime of the accesses (this function only stores
a pointer). The | 160 * subclass manages the lifetime of the accesses (this function only stores
a pointer). The |
219 * GrTextureAccess is typically a member field of the GrEffect subclass. Thi
s must only be | 161 * GrTextureAccess is typically a member field of the GrEffect subclass. Thi
s must only be |
220 * called from the constructor because GrEffects are immutable. | 162 * called from the constructor because GrEffects are immutable. |
221 */ | 163 */ |
222 void addTextureAccess(const GrTextureAccess* textureAccess); | 164 void addTextureAccess(const GrTextureAccess* textureAccess); |
223 | 165 |
224 GrEffect() | 166 GrEffect() |
225 : fWillReadDstColor(false) | 167 : fWillReadDstColor(false) |
226 , fWillReadFragmentPosition(false) | 168 , fWillReadFragmentPosition(false) |
227 , fWillUseInputColor(true) | 169 , fWillUseInputColor(true) |
228 , fHasVertexCode(false) | 170 , fHasVertexCode(false) {} |
229 , fEffectRef(NULL) {} | |
230 | 171 |
231 /** This should be called by GrEffect subclass factories. See the comment on
AutoEffectUnref for | 172 /** This should be called by GrEffect subclass factories. See the comment on
AutoEffectUnref for |
232 an example factory function. */ | 173 an example factory function. */ |
233 static GrEffectRef* CreateEffectRef(GrEffect* effect) { | 174 static GrEffect* CreateEffectRef(GrEffect* effect) { |
234 if (NULL == effect->fEffectRef) { | 175 return SkRef(effect); |
235 effect->fEffectRef = SkNEW_ARGS(GrEffectRef, (effect)); | |
236 } else { | |
237 effect->fEffectRef->ref(); | |
238 } | |
239 return effect->fEffectRef; | |
240 } | 176 } |
241 | 177 |
242 static const GrEffectRef* CreateEffectRef(const GrEffect* effect) { | 178 static const GrEffect* CreateEffectRef(const GrEffect* effect) { |
243 return CreateEffectRef(const_cast<GrEffect*>(effect)); | 179 return CreateEffectRef(const_cast<GrEffect*>(effect)); |
244 } | 180 } |
245 | 181 |
246 /** Used by GR_CREATE_STATIC_EFFECT below */ | |
247 static GrEffectRef* CreateStaticEffectRef(void* refStorage, GrEffect* effect
) { | |
248 SkASSERT(NULL == effect->fEffectRef); | |
249 effect->fEffectRef = SkNEW_PLACEMENT_ARGS(refStorage, GrEffectRef, (effe
ct)); | |
250 return effect->fEffectRef; | |
251 } | |
252 | |
253 | |
254 /** Helper used in subclass factory functions to unref the effect after it h
as been wrapped in a | 182 /** Helper used in subclass factory functions to unref the effect after it h
as been wrapped in a |
255 GrEffectRef. E.g.: | 183 GrEffectRef. E.g.: |
256 | 184 |
257 class EffectSubclass : public GrEffect { | 185 class EffectSubclass : public GrEffect { |
258 public: | 186 public: |
259 GrEffectRef* Create(ParamType1 param1, ParamType2 param2, ...) { | 187 GrEffectRef* Create(ParamType1 param1, ParamType2 param2, ...) { |
260 AutoEffectUnref effect(SkNEW_ARGS(EffectSubclass, (param1, param
2, ...))); | 188 AutoEffectUnref effect(SkNEW_ARGS(EffectSubclass, (param1, param
2, ...))); |
261 return CreateEffectRef(effect); | 189 return CreateEffectRef(effect); |
262 } | 190 } |
263 */ | 191 */ |
264 class AutoEffectUnref { | 192 typedef SkAutoTUnref<GrEffect> AutoEffectUnref; |
265 public: | |
266 AutoEffectUnref(GrEffect* effect) : fEffect(effect) { } | |
267 ~AutoEffectUnref() { fEffect->unref(); } | |
268 operator GrEffect*() { return fEffect; } | |
269 private: | |
270 GrEffect* fEffect; | |
271 }; | |
272 | 193 |
273 /** Helper for getting the GrEffect out of a GrEffectRef and down-casting to
a GrEffect subclass | 194 /** Helper for getting the GrEffect out of a GrEffectRef and down-casting to
a GrEffect subclass |
274 */ | 195 */ |
275 template <typename T> | 196 template <typename T> |
276 static const T& CastEffect(const GrEffect& effectRef) { | 197 static const T& CastEffect(const GrEffect& effectRef) { |
277 return *static_cast<const T*>(&effectRef); | 198 return *static_cast<const T*>(&effectRef); |
278 } | 199 } |
279 | 200 |
280 /** | 201 /** |
281 * If the effect subclass will read the destination pixel value then it must
call this function | 202 * If the effect subclass will read the destination pixel value then it must
call this function |
(...skipping 10 matching lines...) Expand all Loading... |
292 void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; } | 213 void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; } |
293 | 214 |
294 /** | 215 /** |
295 * If the effect will generate a result that does not depend on the input co
lor value then it must | 216 * If the effect will generate a result that does not depend on the input co
lor value then it must |
296 * call this function from its constructor. Otherwise, when its generated ba
ckend-specific code | 217 * call this function from its constructor. Otherwise, when its generated ba
ckend-specific code |
297 * might fail during variable binding due to unused variables. | 218 * might fail during variable binding due to unused variables. |
298 */ | 219 */ |
299 void setWillNotUseInputColor() { fWillUseInputColor = false; } | 220 void setWillNotUseInputColor() { fWillUseInputColor = false; } |
300 | 221 |
301 private: | 222 private: |
302 bool isEqual(const GrEffect& other) const { | |
303 if (&this->getFactory() != &other.getFactory()) { | |
304 return false; | |
305 } | |
306 bool result = this->onIsEqual(other); | |
307 #ifdef SK_DEBUG | |
308 if (result) { | |
309 this->assertEquality(other); | |
310 } | |
311 #endif | |
312 return result; | |
313 } | |
314 | |
315 SkDEBUGCODE(void assertEquality(const GrEffect& other) const;) | 223 SkDEBUGCODE(void assertEquality(const GrEffect& other) const;) |
316 | 224 |
317 /** Subclass implements this to support isEqual(). It will only be called if
it is known that | 225 /** Subclass implements this to support isEqual(). It will only be called if
it is known that |
318 the two effects are of the same subclass (i.e. they return the same obje
ct from | 226 the two effects are of the same subclass (i.e. they return the same obje
ct from |
319 getFactory()).*/ | 227 getFactory()).*/ |
320 virtual bool onIsEqual(const GrEffect& other) const = 0; | 228 virtual bool onIsEqual(const GrEffect& other) const = 0; |
321 | 229 |
322 void EffectRefDestroyed() { fEffectRef = NULL; } | |
323 | |
324 friend class GrEffectRef; // to call EffectRefDestroyed() | |
325 friend class GrEffectStage; // to rewrap GrEffect in GrEffectRef when resto
ring an effect-stage | |
326 // from deferred state, to call isEqual on nake
d GrEffects, and | |
327 // to inc/dec deferred ref counts. | |
328 friend class GrVertexEffect; // to set fHasVertexCode and build fVertexAttri
bTypes. | 230 friend class GrVertexEffect; // to set fHasVertexCode and build fVertexAttri
bTypes. |
329 | 231 |
330 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms; | 232 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms; |
331 SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses; | 233 SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses; |
332 SkSTArray<kMaxVertexAttribs, GrSLType, true> fVertexAttribTypes; | 234 SkSTArray<kMaxVertexAttribs, GrSLType, true> fVertexAttribTypes; |
333 bool fWillReadDstColor; | 235 bool fWillReadDstColor; |
334 bool fWillReadFragmentPosition; | 236 bool fWillReadFragmentPosition; |
335 bool fWillUseInputColor; | 237 bool fWillUseInputColor; |
336 bool fHasVertexCode; | 238 bool fHasVertexCode; |
337 GrEffectRef* fEffectRef; | |
338 | 239 |
339 typedef SkRefCnt INHERITED; | 240 typedef SkRefCnt INHERITED; |
340 }; | 241 }; |
341 | 242 |
342 inline GrEffectRef::GrEffectRef(GrEffect* effect) { | 243 typedef GrEffect GrEffectRef; |
343 SkASSERT(NULL != effect); | |
344 effect->ref(); | |
345 fEffect = effect; | |
346 } | |
347 | 244 |
348 /** | 245 /** |
349 * This creates an effect outside of the effect memory pool. The effect's destru
ctor will be called | 246 * This creates an effect outside of the effect memory pool. The effect's destru
ctor will be called |
350 * at global destruction time. NAME will be the name of the created GrEffectRef. | 247 * at global destruction time. NAME will be the name of the created GrEffect. |
351 */ | 248 */ |
352 #define GR_CREATE_STATIC_EFFECT(NAME, EFFECT_CLASS, ARGS)
\ | 249 #define GR_CREATE_STATIC_EFFECT(NAME, EFFECT_CLASS, ARGS)
\ |
353 enum {
\ | 250 static SkAlignedSStorage<sizeof(EFFECT_CLASS)> g_##NAME##_Storage;
\ |
354 k_##NAME##_EffectRefOffset = GR_CT_ALIGN_UP(sizeof(EFFECT_CLASS), 8),
\ | 251 static GrEffect* NAME SkNEW_PLACEMENT_ARGS(g_##NAME##_Storage.get(), EFFECT_CLAS
S, ARGS); \ |
355 k_##NAME##_StorageSize = k_##NAME##_EffectRefOffset + sizeof(GrEffectRef)
\ | 252 static SkAutoTDestroy<GrEffect> NAME##_ad(NAME); |
356 };
\ | |
357 static SkAlignedSStorage<k_##NAME##_StorageSize> g_##NAME##_Storage;
\ | |
358 static void* NAME##_RefLocation = (char*)g_##NAME##_Storage.get() + k_##NAME##_E
ffectRefOffset; \ | |
359 static GrEffect* NAME##_Effect SkNEW_PLACEMENT_ARGS(g_##NAME##_Storage.get(), EF
FECT_CLASS, ARGS);\ | |
360 static SkAutoTDestroy<GrEffect> NAME##_ad(NAME##_Effect);
\ | |
361 static GrEffectRef* NAME(GrEffect::CreateStaticEffectRef(NAME##_RefLocation, NAM
E##_Effect)); \ | |
362 static SkAutoTDestroy<GrEffectRef> NAME##_Ref_ad(NAME) | |
363 | 253 |
364 | 254 |
365 #endif | 255 #endif |
OLD | NEW |