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