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: 23 explicit GrEffectStage(const GrEffectRef* effectRef, int attrIndex0 = -1, int attrIndex1 = -1) fEffectRef(SkRef (effectRef))24 : fEffectRef(SkRef(effectRef)) { 25 fCoordChangeMatrixSet = false; 26 fVertexAttribIndices[0] = attrIndex0; 27 fVertexAttribIndices[1] = attrIndex1; 28 } 29 GrEffectStage(const GrEffectStage & other)30 GrEffectStage(const GrEffectStage& other) { 31 *this = other; 32 } 33 34 class DeferredStage; 35 // This constructor balances DeferredStage::saveFrom(). GrEffectStage(const DeferredStage & deferredStage)36 explicit GrEffectStage(const DeferredStage& deferredStage) { 37 deferredStage.restoreTo(this); 38 } 39 40 GrEffectStage& operator= (const GrEffectStage& other) { 41 fCoordChangeMatrixSet = other.fCoordChangeMatrixSet; 42 if (other.fCoordChangeMatrixSet) { 43 fCoordChangeMatrix = other.fCoordChangeMatrix; 44 } 45 fEffectRef.reset(SkRef(other.fEffectRef.get())); 46 memcpy(fVertexAttribIndices, other.fVertexAttribIndices, sizeof(fVertexAttribIndices)); 47 return *this; 48 } 49 50 bool operator== (const GrEffectStage& other) const { 51 SkASSERT(NULL != fEffectRef.get()); 52 SkASSERT(NULL != other.fEffectRef.get()); 53 54 if (!(*this->getEffect())->isEqual(*other.getEffect())) { 55 return false; 56 } 57 58 if (fCoordChangeMatrixSet != other.fCoordChangeMatrixSet) { 59 return false; 60 } 61 62 if (!fCoordChangeMatrixSet) { 63 return true; 64 } 65 66 return fCoordChangeMatrix == other.fCoordChangeMatrix; 67 } 68 69 bool operator!= (const GrEffectStage& s) const { return !(*this == s); } 70 71 /** 72 * This is called when the coordinate system in which the geometry is specified will change. 73 * 74 * @param matrix The transformation from the old coord system in which geometry is specified 75 * to the new one from which it will actually be drawn. 76 */ localCoordChange(const SkMatrix & matrix)77 void localCoordChange(const SkMatrix& matrix) { 78 if (fCoordChangeMatrixSet) { 79 fCoordChangeMatrix.preConcat(matrix); 80 } else { 81 fCoordChangeMatrixSet = true; 82 fCoordChangeMatrix = matrix; 83 } 84 } 85 86 class SavedCoordChange { 87 private: 88 bool fCoordChangeMatrixSet; 89 SkMatrix fCoordChangeMatrix; 90 SkDEBUGCODE(mutable SkAutoTUnref<const GrEffectRef> fEffectRef;) 91 92 friend class GrEffectStage; 93 }; 94 95 /** 96 * This gets the current coordinate system change. It is the accumulation of 97 * localCoordChange calls since the effect was installed. It is used when then caller 98 * wants to temporarily change the source geometry coord system, draw something, and then 99 * restore the previous coord system (e.g. temporarily draw in device coords). 100 */ saveCoordChange(SavedCoordChange * savedCoordChange)101 void saveCoordChange(SavedCoordChange* savedCoordChange) const { 102 savedCoordChange->fCoordChangeMatrixSet = fCoordChangeMatrixSet; 103 if (fCoordChangeMatrixSet) { 104 savedCoordChange->fCoordChangeMatrix = fCoordChangeMatrix; 105 } 106 SkASSERT(NULL == savedCoordChange->fEffectRef.get()); 107 SkDEBUGCODE(SkRef(fEffectRef.get());) 108 SkDEBUGCODE(savedCoordChange->fEffectRef.reset(fEffectRef.get());) 109 } 110 111 /** 112 * This balances the saveCoordChange call. 113 */ restoreCoordChange(const SavedCoordChange & savedCoordChange)114 void restoreCoordChange(const SavedCoordChange& savedCoordChange) { 115 fCoordChangeMatrixSet = savedCoordChange.fCoordChangeMatrixSet; 116 if (fCoordChangeMatrixSet) { 117 fCoordChangeMatrix = savedCoordChange.fCoordChangeMatrix; 118 } 119 SkASSERT(savedCoordChange.fEffectRef.get() == fEffectRef); 120 SkDEBUGCODE(savedCoordChange.fEffectRef.reset(NULL);) 121 } 122 123 /** 124 * Used when storing a deferred GrDrawState. The DeferredStage allows resources owned by its 125 * GrEffect to be recycled through the cache. 126 */ 127 class DeferredStage { 128 public: DeferredStage()129 DeferredStage() : fEffect(NULL) { 130 SkDEBUGCODE(fInitialized = false;) 131 } 132 ~DeferredStage()133 ~DeferredStage() { 134 if (NULL != fEffect) { 135 fEffect->decDeferredRefCounts(); 136 } 137 } 138 saveFrom(const GrEffectStage & stage)139 void saveFrom(const GrEffectStage& stage) { 140 SkASSERT(!fInitialized); 141 SkASSERT(NULL != stage.fEffectRef.get()); 142 stage.fEffectRef->get()->incDeferredRefCounts(); 143 fEffect = stage.fEffectRef->get(); 144 fCoordChangeMatrixSet = stage.fCoordChangeMatrixSet; 145 if (fCoordChangeMatrixSet) { 146 fCoordChangeMatrix = stage.fCoordChangeMatrix; 147 } 148 fVertexAttribIndices[0] = stage.fVertexAttribIndices[0]; 149 fVertexAttribIndices[1] = stage.fVertexAttribIndices[1]; 150 SkDEBUGCODE(fInitialized = true;) 151 } 152 restoreTo(GrEffectStage * stage)153 void restoreTo(GrEffectStage* stage) const { 154 SkASSERT(fInitialized); 155 stage->fEffectRef.reset(GrEffect::CreateEffectRef(fEffect)); 156 stage->fCoordChangeMatrixSet = fCoordChangeMatrixSet; 157 if (fCoordChangeMatrixSet) { 158 stage->fCoordChangeMatrix = fCoordChangeMatrix; 159 } 160 stage->fVertexAttribIndices[0] = fVertexAttribIndices[0]; 161 stage->fVertexAttribIndices[1] = fVertexAttribIndices[1]; 162 } 163 isEqual(const GrEffectStage & stage,bool ignoreCoordChange)164 bool isEqual(const GrEffectStage& stage, bool ignoreCoordChange) const { 165 if (fVertexAttribIndices[0] != stage.fVertexAttribIndices[0] || 166 fVertexAttribIndices[1] != stage.fVertexAttribIndices[1]) { 167 return false; 168 } 169 170 if (!(*stage.getEffect())->isEqual(*fEffect)) { 171 return false; 172 } 173 174 if (ignoreCoordChange) { 175 // ignore the coordinate change matrix since there are 176 // explicit uv coordinates 177 return true; 178 } 179 180 if (fCoordChangeMatrixSet != stage.fCoordChangeMatrixSet) { 181 return false; 182 } 183 184 if (!fCoordChangeMatrixSet) { 185 return true; 186 } 187 188 return fCoordChangeMatrix == stage.fCoordChangeMatrix; 189 } 190 191 private: 192 const GrEffect* fEffect; 193 bool fCoordChangeMatrixSet; 194 SkMatrix fCoordChangeMatrix; 195 int fVertexAttribIndices[2]; 196 SkDEBUGCODE(bool fInitialized;) 197 }; 198 199 /** 200 * Gets the matrix representing all changes of coordinate system since the GrEffect was 201 * installed in the stage. 202 */ getCoordChangeMatrix()203 const SkMatrix& getCoordChangeMatrix() const { 204 if (fCoordChangeMatrixSet) { 205 return fCoordChangeMatrix; 206 } else { 207 return SkMatrix::I(); 208 } 209 } 210 getEffect()211 const GrEffectRef* getEffect() const { return fEffectRef.get(); } 212 getVertexAttribIndices()213 const int* getVertexAttribIndices() const { return fVertexAttribIndices; } getVertexAttribIndexCount()214 int getVertexAttribIndexCount() const { return fEffectRef->get()->numVertexAttribs(); } 215 216 private: 217 bool fCoordChangeMatrixSet; 218 SkMatrix fCoordChangeMatrix; 219 SkAutoTUnref<const GrEffectRef> fEffectRef; 220 int fVertexAttribIndices[2]; 221 }; 222 223 #endif 224