1 2 /* 3 * Copyright 2010 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 11 #ifndef GrEffectStage_DEFINED 12 #define GrEffectStage_DEFINED 13 14 #include "GrBackendEffectFactory.h" 15 #include "GrEffect.h" 16 #include "SkMatrix.h" 17 #include "GrTypes.h" 18 19 #include "SkShader.h" 20 21 class GrEffectStage { 22 public: GrEffectStage()23 GrEffectStage() 24 : fEffectRef (NULL) { 25 GR_DEBUGCODE(fSavedCoordChangeCnt = 0;) 26 } 27 ~GrEffectStage()28 ~GrEffectStage() { 29 GrSafeUnref(fEffectRef); 30 GrAssert(0 == fSavedCoordChangeCnt); 31 } 32 33 bool operator ==(const GrEffectStage& other) const { 34 // first handle cases where one or the other has no effect 35 if (NULL == fEffectRef) { 36 return NULL == other.fEffectRef; 37 } else if (NULL == other.fEffectRef) { 38 return false; 39 } 40 41 if (!(*this->getEffect())->isEqual(*other.getEffect())) { 42 return false; 43 } 44 45 return fCoordChangeMatrix == other.fCoordChangeMatrix; 46 } 47 48 bool operator !=(const GrEffectStage& s) const { return !(*this == s); } 49 50 GrEffectStage& operator =(const GrEffectStage& other) { 51 GrSafeAssign(fEffectRef, other.fEffectRef); 52 if (NULL != fEffectRef) { 53 fCoordChangeMatrix = other.fCoordChangeMatrix; 54 } 55 return *this; 56 } 57 58 /** 59 * This is called when the coordinate system in which the geometry is specified will change. 60 * 61 * @param matrix The transformation from the old coord system to the new one. 62 */ preConcatCoordChange(const SkMatrix & matrix)63 void preConcatCoordChange(const SkMatrix& matrix) { fCoordChangeMatrix.preConcat(matrix); } 64 65 class SavedCoordChange { 66 private: 67 SkMatrix fCoordChangeMatrix; 68 GR_DEBUGCODE(mutable SkAutoTUnref<const GrEffectRef> fEffectRef;) 69 70 friend class GrEffectStage; 71 }; 72 73 /** 74 * This gets the current coordinate system change. It is the accumulation of 75 * preConcatCoordChange calls since the effect was installed. It is used when then caller 76 * wants to temporarily change the source geometry coord system, draw something, and then 77 * restore the previous coord system (e.g. temporarily draw in device coords). 78 */ saveCoordChange(SavedCoordChange * savedCoordChange)79 void saveCoordChange(SavedCoordChange* savedCoordChange) const { 80 savedCoordChange->fCoordChangeMatrix = fCoordChangeMatrix; 81 GrAssert(NULL == savedCoordChange->fEffectRef.get()); 82 GR_DEBUGCODE(GrSafeRef(fEffectRef);) 83 GR_DEBUGCODE(savedCoordChange->fEffectRef.reset(fEffectRef);) 84 GR_DEBUGCODE(++fSavedCoordChangeCnt); 85 } 86 87 /** 88 * This balances the saveCoordChange call. 89 */ restoreCoordChange(const SavedCoordChange & savedCoordChange)90 void restoreCoordChange(const SavedCoordChange& savedCoordChange) { 91 fCoordChangeMatrix = savedCoordChange.fCoordChangeMatrix; 92 GrAssert(savedCoordChange.fEffectRef.get() == fEffectRef); 93 GR_DEBUGCODE(--fSavedCoordChangeCnt); 94 GR_DEBUGCODE(savedCoordChange.fEffectRef.reset(NULL);) 95 } 96 97 /** 98 * Used when storing a deferred GrDrawState. The DeferredStage allows resources owned by its 99 * GrEffect to be recycled through the cache. 100 */ 101 class DeferredStage { 102 public: DeferredStage()103 DeferredStage() : fEffect(NULL) { 104 SkDEBUGCODE(fInitialized = false;) 105 } 106 ~DeferredStage()107 ~DeferredStage() { 108 if (NULL != fEffect) { 109 fEffect->decDeferredRefCounts(); 110 } 111 } 112 saveFrom(const GrEffectStage & stage)113 void saveFrom(const GrEffectStage& stage) { 114 GrAssert(!fInitialized); 115 if (NULL != stage.fEffectRef) { 116 stage.fEffectRef->get()->incDeferredRefCounts(); 117 fEffect = stage.fEffectRef->get(); 118 fCoordChangeMatrix = stage.fCoordChangeMatrix; 119 } 120 SkDEBUGCODE(fInitialized = true;) 121 } 122 restoreTo(GrEffectStage * stage)123 void restoreTo(GrEffectStage* stage) { 124 GrAssert(fInitialized); 125 const GrEffectRef* oldEffectRef = stage->fEffectRef; 126 if (NULL != fEffect) { 127 stage->fEffectRef = GrEffect::CreateEffectRef(fEffect); 128 stage->fCoordChangeMatrix = fCoordChangeMatrix; 129 } else { 130 stage->fEffectRef = NULL; 131 } 132 SkSafeUnref(oldEffectRef); 133 } 134 isEqual(const GrEffectStage & stage)135 bool isEqual(const GrEffectStage& stage) const { 136 if (NULL == stage.fEffectRef) { 137 return NULL == fEffect; 138 } else if (NULL == fEffect) { 139 return false; 140 } 141 142 if (!(*stage.getEffect())->isEqual(*fEffect)) { 143 return false; 144 } 145 146 return fCoordChangeMatrix == stage.fCoordChangeMatrix; 147 } 148 149 private: 150 const GrEffect* fEffect; 151 SkMatrix fCoordChangeMatrix; 152 SkDEBUGCODE(bool fInitialized;) 153 }; 154 155 /** 156 * Gets the matrix representing all changes of coordinate system since the GrEffect was 157 * installed in the stage. 158 */ getCoordChangeMatrix()159 const SkMatrix& getCoordChangeMatrix() const { return fCoordChangeMatrix; } 160 reset()161 void reset() { 162 GrSafeSetNull(fEffectRef); 163 } 164 setEffect(const GrEffectRef * EffectRef)165 const GrEffectRef* setEffect(const GrEffectRef* EffectRef) { 166 GrAssert(0 == fSavedCoordChangeCnt); 167 GrSafeAssign(fEffectRef, EffectRef); 168 fCoordChangeMatrix.reset(); 169 return EffectRef; 170 } 171 getEffect()172 const GrEffectRef* getEffect() const { return fEffectRef; } 173 174 private: 175 SkMatrix fCoordChangeMatrix; 176 const GrEffectRef* fEffectRef; 177 178 GR_DEBUGCODE(mutable int fSavedCoordChangeCnt;) 179 }; 180 181 #endif 182