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 |
24 /** Provides custom vertex shader, fragment shader, uniform data for a particula
r stage of the | 66 /** Provides custom vertex shader, fragment shader, uniform data for a particula
r stage of the |
25 Ganesh shading pipeline. | 67 Ganesh shading pipeline. |
26 Subclasses must have a function that produces a human-readable name: | 68 Subclasses must have a function that produces a human-readable name: |
27 static const char* Name(); | 69 static const char* Name(); |
28 GrEffect objects *must* be immutable: after being constructed, their fields
may not change. | 70 GrEffect objects *must* be immutable: after being constructed, their fields
may not change. |
29 | 71 |
30 Dynamically allocated GrEffects are managed by a per-thread memory pool. The
ref count of an | 72 GrEffect subclass objects should be created by factory functions that return
GrEffectRef. |
31 effect must reach 0 before the thread terminates and the pool is destroyed.
To create a static | 73 There is no public way to wrap a GrEffect in a GrEffectRef. Thus, a factory
should be a static |
32 effect use the macro GR_CREATE_STATIC_EFFECT declared below. | 74 member function of a GrEffect subclass. |
| 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. |
33 */ | 82 */ |
34 class GrEffect : public SkRefCnt { | 83 class GrEffect : private SkRefCnt { |
35 public: | 84 public: |
36 SK_DECLARE_INST_COUNT(GrEffect) | 85 SK_DECLARE_INST_COUNT(GrEffect) |
37 | 86 |
38 virtual ~GrEffect(); | 87 virtual ~GrEffect(); |
39 | 88 |
40 /** | 89 /** |
41 * This function is used to perform optimizations. When called the color and
validFlags params | 90 * This function is used to perform optimizations. When called the color and
validFlags params |
42 * indicate whether the input components to this effect in the FS will have
known values. | 91 * indicate whether the input components to this effect in the FS will have
known values. |
43 * validFlags is a bitfield of GrColorComponentFlags. The function updates b
oth params to | 92 * validFlags is a bitfield of GrColorComponentFlags. The function updates b
oth params to |
44 * indicate known values of its output. A component of the color param only
has meaning if the | 93 * indicate known values of its output. A component of the color param only
has meaning if the |
(...skipping 23 matching lines...) Expand all Loading... |
68 | 117 |
69 /** Returns true if this and other effect conservatively draw identically. I
t can only return | 118 /** Returns true if this and other effect conservatively draw identically. I
t can only return |
70 true when the two effects are of the same subclass (i.e. they return the
same object from | 119 true when the two effects are of the same subclass (i.e. they return the
same object from |
71 from getFactory()). | 120 from getFactory()). |
72 | 121 |
73 A return value of true from isEqual() should not be used to test whether
the effects would | 122 A return value of true from isEqual() should not be used to test whether
the effects would |
74 generate the same shader code. To test for identical code generation use
the EffectKey | 123 generate the same shader code. To test for identical code generation use
the EffectKey |
75 computed by the GrBackendEffectFactory: | 124 computed by the GrBackendEffectFactory: |
76 effectA.getFactory().glEffectKey(effectA) == effectB.getFactory().gl
EffectKey(effectB). | 125 effectA.getFactory().glEffectKey(effectA) == effectB.getFactory().gl
EffectKey(effectB). |
77 */ | 126 */ |
78 bool isEqual(const GrEffect& other) const { | 127 bool isEqual(const GrEffectRef& other) const { |
79 if (&this->getFactory() != &other.getFactory()) { | 128 return this->isEqual(*other.get()); |
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; | |
89 } | 129 } |
90 | 130 |
91 /** Human-meaningful string to identify this effect; may be embedded | 131 /** Human-meaningful string to identify this effect; may be embedded |
92 in generated shader code. */ | 132 in generated shader code. */ |
93 const char* name() const; | 133 const char* name() const; |
94 | 134 |
95 int numTransforms() const { return fCoordTransforms.count(); } | 135 int numTransforms() const { return fCoordTransforms.count(); } |
96 | 136 |
97 /** Returns the coordinate transformation at index. index must be valid acco
rding to | 137 /** Returns the coordinate transformation at index. index must be valid acco
rding to |
98 numTransforms(). */ | 138 numTransforms(). */ |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 void* operator new(size_t size); | 178 void* operator new(size_t size); |
139 void operator delete(void* target); | 179 void operator delete(void* target); |
140 | 180 |
141 void* operator new(size_t size, void* placement) { | 181 void* operator new(size_t size, void* placement) { |
142 return ::operator new(size, placement); | 182 return ::operator new(size, placement); |
143 } | 183 } |
144 void operator delete(void* target, void* placement) { | 184 void operator delete(void* target, void* placement) { |
145 ::operator delete(target, placement); | 185 ::operator delete(target, placement); |
146 } | 186 } |
147 | 187 |
| 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 |
148 protected: | 206 protected: |
149 /** | 207 /** |
150 * Subclasses call this from their constructor to register coordinate transf
ormations. The | 208 * Subclasses call this from their constructor to register coordinate transf
ormations. The |
151 * effect subclass manages the lifetime of the transformations (this functio
n only stores a | 209 * effect subclass manages the lifetime of the transformations (this functio
n only stores a |
152 * pointer). The GrCoordTransform is typically a member field of the GrEffec
t subclass. When the | 210 * pointer). The GrCoordTransform is typically a member field of the GrEffec
t subclass. When the |
153 * matrix has perspective, the transformed coordinates will have 3 component
s. Otherwise they'll | 211 * matrix has perspective, the transformed coordinates will have 3 component
s. Otherwise they'll |
154 * have 2. This must only be called from the constructor because GrEffects a
re immutable. | 212 * have 2. This must only be called from the constructor because GrEffects a
re immutable. |
155 */ | 213 */ |
156 void addCoordTransform(const GrCoordTransform* coordTransform); | 214 void addCoordTransform(const GrCoordTransform* coordTransform); |
157 | 215 |
158 /** | 216 /** |
159 * Subclasses call this from their constructor to register GrTextureAccesses
. The effect | 217 * Subclasses call this from their constructor to register GrTextureAccesses
. The effect |
160 * subclass manages the lifetime of the accesses (this function only stores
a pointer). The | 218 * subclass manages the lifetime of the accesses (this function only stores
a pointer). The |
161 * GrTextureAccess is typically a member field of the GrEffect subclass. Thi
s must only be | 219 * GrTextureAccess is typically a member field of the GrEffect subclass. Thi
s must only be |
162 * called from the constructor because GrEffects are immutable. | 220 * called from the constructor because GrEffects are immutable. |
163 */ | 221 */ |
164 void addTextureAccess(const GrTextureAccess* textureAccess); | 222 void addTextureAccess(const GrTextureAccess* textureAccess); |
165 | 223 |
166 GrEffect() | 224 GrEffect() |
167 : fWillReadDstColor(false) | 225 : fWillReadDstColor(false) |
168 , fWillReadFragmentPosition(false) | 226 , fWillReadFragmentPosition(false) |
169 , fWillUseInputColor(true) | 227 , fWillUseInputColor(true) |
170 , fHasVertexCode(false) {} | 228 , fHasVertexCode(false) |
| 229 , fEffectRef(NULL) {} |
171 | 230 |
172 /** This should be called by GrEffect subclass factories. See the comment on
AutoEffectUnref for | 231 /** This should be called by GrEffect subclass factories. See the comment on
AutoEffectUnref for |
173 an example factory function. */ | 232 an example factory function. */ |
174 static GrEffect* CreateEffectRef(GrEffect* effect) { | 233 static GrEffectRef* CreateEffectRef(GrEffect* effect) { |
175 return SkRef(effect); | 234 if (NULL == effect->fEffectRef) { |
| 235 effect->fEffectRef = SkNEW_ARGS(GrEffectRef, (effect)); |
| 236 } else { |
| 237 effect->fEffectRef->ref(); |
| 238 } |
| 239 return effect->fEffectRef; |
176 } | 240 } |
177 | 241 |
178 static const GrEffect* CreateEffectRef(const GrEffect* effect) { | 242 static const GrEffectRef* CreateEffectRef(const GrEffect* effect) { |
179 return CreateEffectRef(const_cast<GrEffect*>(effect)); | 243 return CreateEffectRef(const_cast<GrEffect*>(effect)); |
180 } | 244 } |
181 | 245 |
| 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 |
182 /** Helper used in subclass factory functions to unref the effect after it h
as been wrapped in a | 254 /** Helper used in subclass factory functions to unref the effect after it h
as been wrapped in a |
183 GrEffectRef. E.g.: | 255 GrEffectRef. E.g.: |
184 | 256 |
185 class EffectSubclass : public GrEffect { | 257 class EffectSubclass : public GrEffect { |
186 public: | 258 public: |
187 GrEffectRef* Create(ParamType1 param1, ParamType2 param2, ...) { | 259 GrEffectRef* Create(ParamType1 param1, ParamType2 param2, ...) { |
188 AutoEffectUnref effect(SkNEW_ARGS(EffectSubclass, (param1, param
2, ...))); | 260 AutoEffectUnref effect(SkNEW_ARGS(EffectSubclass, (param1, param
2, ...))); |
189 return CreateEffectRef(effect); | 261 return CreateEffectRef(effect); |
190 } | 262 } |
191 */ | 263 */ |
192 typedef SkAutoTUnref<GrEffect> AutoEffectUnref; | 264 class AutoEffectUnref { |
| 265 public: |
| 266 AutoEffectUnref(GrEffect* effect) : fEffect(effect) { } |
| 267 ~AutoEffectUnref() { fEffect->unref(); } |
| 268 operator GrEffect*() { return fEffect; } |
| 269 private: |
| 270 GrEffect* fEffect; |
| 271 }; |
193 | 272 |
194 /** Helper for getting the GrEffect out of a GrEffectRef and down-casting to
a GrEffect subclass | 273 /** Helper for getting the GrEffect out of a GrEffectRef and down-casting to
a GrEffect subclass |
195 */ | 274 */ |
196 template <typename T> | 275 template <typename T> |
197 static const T& CastEffect(const GrEffect& effectRef) { | 276 static const T& CastEffect(const GrEffect& effectRef) { |
198 return *static_cast<const T*>(&effectRef); | 277 return *static_cast<const T*>(&effectRef); |
199 } | 278 } |
200 | 279 |
201 /** | 280 /** |
202 * If the effect subclass will read the destination pixel value then it must
call this function | 281 * If the effect subclass will read the destination pixel value then it must
call this function |
(...skipping 10 matching lines...) Expand all Loading... |
213 void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; } | 292 void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; } |
214 | 293 |
215 /** | 294 /** |
216 * If the effect will generate a result that does not depend on the input co
lor value then it must | 295 * If the effect will generate a result that does not depend on the input co
lor value then it must |
217 * call this function from its constructor. Otherwise, when its generated ba
ckend-specific code | 296 * call this function from its constructor. Otherwise, when its generated ba
ckend-specific code |
218 * might fail during variable binding due to unused variables. | 297 * might fail during variable binding due to unused variables. |
219 */ | 298 */ |
220 void setWillNotUseInputColor() { fWillUseInputColor = false; } | 299 void setWillNotUseInputColor() { fWillUseInputColor = false; } |
221 | 300 |
222 private: | 301 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 |
223 SkDEBUGCODE(void assertEquality(const GrEffect& other) const;) | 315 SkDEBUGCODE(void assertEquality(const GrEffect& other) const;) |
224 | 316 |
225 /** Subclass implements this to support isEqual(). It will only be called if
it is known that | 317 /** Subclass implements this to support isEqual(). It will only be called if
it is known that |
226 the two effects are of the same subclass (i.e. they return the same obje
ct from | 318 the two effects are of the same subclass (i.e. they return the same obje
ct from |
227 getFactory()).*/ | 319 getFactory()).*/ |
228 virtual bool onIsEqual(const GrEffect& other) const = 0; | 320 virtual bool onIsEqual(const GrEffect& other) const = 0; |
229 | 321 |
| 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. |
230 friend class GrVertexEffect; // to set fHasVertexCode and build fVertexAttri
bTypes. | 328 friend class GrVertexEffect; // to set fHasVertexCode and build fVertexAttri
bTypes. |
231 | 329 |
232 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms; | 330 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms; |
233 SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses; | 331 SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses; |
234 SkSTArray<kMaxVertexAttribs, GrSLType, true> fVertexAttribTypes; | 332 SkSTArray<kMaxVertexAttribs, GrSLType, true> fVertexAttribTypes; |
235 bool fWillReadDstColor; | 333 bool fWillReadDstColor; |
236 bool fWillReadFragmentPosition; | 334 bool fWillReadFragmentPosition; |
237 bool fWillUseInputColor; | 335 bool fWillUseInputColor; |
238 bool fHasVertexCode; | 336 bool fHasVertexCode; |
| 337 GrEffectRef* fEffectRef; |
239 | 338 |
240 typedef SkRefCnt INHERITED; | 339 typedef SkRefCnt INHERITED; |
241 }; | 340 }; |
242 | 341 |
243 typedef GrEffect GrEffectRef; | 342 inline GrEffectRef::GrEffectRef(GrEffect* effect) { |
| 343 SkASSERT(NULL != effect); |
| 344 effect->ref(); |
| 345 fEffect = effect; |
| 346 } |
244 | 347 |
245 /** | 348 /** |
246 * This creates an effect outside of the effect memory pool. The effect's destru
ctor will be called | 349 * This creates an effect outside of the effect memory pool. The effect's destru
ctor will be called |
247 * at global destruction time. NAME will be the name of the created GrEffect. | 350 * at global destruction time. NAME will be the name of the created GrEffectRef. |
248 */ | 351 */ |
249 #define GR_CREATE_STATIC_EFFECT(NAME, EFFECT_CLASS, ARGS)
\ | 352 #define GR_CREATE_STATIC_EFFECT(NAME, EFFECT_CLASS, ARGS)
\ |
250 static SkAlignedSStorage<sizeof(EFFECT_CLASS)> g_##NAME##_Storage;
\ | 353 enum {
\ |
251 static GrEffect* NAME SkNEW_PLACEMENT_ARGS(g_##NAME##_Storage.get(), EFFECT_CLAS
S, ARGS); \ | 354 k_##NAME##_EffectRefOffset = GR_CT_ALIGN_UP(sizeof(EFFECT_CLASS), 8),
\ |
252 static SkAutoTDestroy<GrEffect> NAME##_ad(NAME); | 355 k_##NAME##_StorageSize = k_##NAME##_EffectRefOffset + sizeof(GrEffectRef)
\ |
| 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) |
253 | 363 |
254 | 364 |
255 #endif | 365 #endif |
OLD | NEW |