| 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 |