1 2 /* 3 * Copyright 2011 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 #ifndef GrPaint_DEFINED 11 #define GrPaint_DEFINED 12 13 #include "GrColor.h" 14 #include "GrEffectStage.h" 15 16 #include "SkXfermode.h" 17 18 /** 19 * The paint describes how color and coverage are computed at each pixel by GrContext draw 20 * functions and the how color is blended with the destination pixel. 21 * 22 * The paint allows installation of custom color and coverage stages. New types of stages are 23 * created by subclassing GrEffect. 24 * 25 * The primitive color computation starts with the color specified by setColor(). This color is the 26 * input to the first color stage. Each color stage feeds its output to the next color stage. The 27 * final color stage's output color is input to the color filter specified by 28 * setXfermodeColorFilter which produces the final source color, S. 29 * 30 * Fractional pixel coverage follows a similar flow. The coverage is initially the value specified 31 * by setCoverage(). This is input to the first coverage stage. Coverage stages are chained 32 * together in the same manner as color stages. The output of the last stage is modulated by any 33 * fractional coverage produced by anti-aliasing. This last step produces the final coverage, C. 34 * 35 * setBlendFunc() specifies blending coefficients for S (described above) and D, the initial value 36 * of the destination pixel, labeled Bs and Bd respectively. The final value of the destination 37 * pixel is then D' = (1-C)*D + C*(Bd*D + Bs*S). 38 * 39 * Note that the coverage is applied after the blend. This is why they are computed as distinct 40 * values. 41 * 42 * TODO: Encapsulate setXfermodeColorFilter in a GrEffect and remove from GrPaint. 43 */ 44 class GrPaint { 45 public: 46 GrPaint() { this->reset(); } 47 48 GrPaint(const GrPaint& paint) { *this = paint; } 49 50 ~GrPaint() {} 51 52 /** 53 * Sets the blending coefficients to use to blend the final primitive color with the 54 * destination color. Defaults to kOne for src and kZero for dst (i.e. src mode). 55 */ 56 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 57 fSrcBlendCoeff = srcCoeff; 58 fDstBlendCoeff = dstCoeff; 59 } 60 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlendCoeff; } 61 GrBlendCoeff getDstBlendCoeff() const { return fDstBlendCoeff; } 62 63 /** 64 * The initial color of the drawn primitive. Defaults to solid white. 65 */ 66 void setColor(GrColor color) { fColor = color; } 67 GrColor getColor() const { return fColor; } 68 69 /** 70 * Applies fractional coverage to the entire drawn primitive. Defaults to 0xff. 71 */ 72 void setCoverage(uint8_t coverage) { fCoverage = coverage; } 73 uint8_t getCoverage() const { return fCoverage; } 74 75 /** 76 * Should primitives be anti-aliased or not. Defaults to false. 77 */ 78 void setAntiAlias(bool aa) { fAntiAlias = aa; } 79 bool isAntiAlias() const { return fAntiAlias; } 80 81 /** 82 * Should dithering be applied. Defaults to false. 83 */ 84 void setDither(bool dither) { fDither = dither; } 85 bool isDither() const { return fDither; } 86 87 /** 88 * Enables a SkXfermode::Mode-based color filter applied to the primitive color. The constant 89 * color passed to this function is considered the "src" color and the primitive's color is 90 * considered the "dst" color. Defaults to kDst_Mode which equates to simply passing through 91 * the primitive color unmodified. 92 */ 93 void setXfermodeColorFilter(SkXfermode::Mode mode, GrColor color) { 94 fColorFilterColor = color; 95 fColorFilterXfermode = mode; 96 } 97 SkXfermode::Mode getColorFilterMode() const { return fColorFilterXfermode; } 98 GrColor getColorFilterColor() const { return fColorFilterColor; } 99 100 /** 101 * Disables the SkXfermode::Mode color filter. 102 */ 103 void resetColorFilter() { 104 fColorFilterXfermode = SkXfermode::kDst_Mode; 105 fColorFilterColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff); 106 } 107 108 /** 109 * Appends an additional color effect to the color computation. 110 */ 111 const GrEffectRef* addColorEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) { 112 GrAssert(NULL != effect); 113 SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect, attr0, attr1)); 114 return effect; 115 } 116 117 /** 118 * Appends an additional coverage effect to the coverage computation. 119 */ 120 const GrEffectRef* addCoverageEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) { 121 GrAssert(NULL != effect); 122 SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect, attr0, attr1)); 123 return effect; 124 } 125 126 /** 127 * Helpers for adding color or coverage effects that sample a texture. The matrix is applied 128 * to the src space position to compute texture coordinates. 129 */ 130 void addColorTextureEffect(GrTexture* texture, const SkMatrix& matrix); 131 void addCoverageTextureEffect(GrTexture* texture, const SkMatrix& matrix); 132 133 void addColorTextureEffect(GrTexture* texture, 134 const SkMatrix& matrix, 135 const GrTextureParams& params); 136 void addCoverageTextureEffect(GrTexture* texture, 137 const SkMatrix& matrix, 138 const GrTextureParams& params); 139 140 int numColorStages() const { return fColorStages.count(); } 141 int numCoverageStages() const { return fCoverageStages.count(); } 142 int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); } 143 144 const GrEffectStage& getColorStage(int s) const { return fColorStages[s]; } 145 const GrEffectStage& getCoverageStage(int s) const { return fCoverageStages[s]; } 146 147 GrPaint& operator=(const GrPaint& paint) { 148 fSrcBlendCoeff = paint.fSrcBlendCoeff; 149 fDstBlendCoeff = paint.fDstBlendCoeff; 150 fAntiAlias = paint.fAntiAlias; 151 fDither = paint.fDither; 152 153 fColor = paint.fColor; 154 fCoverage = paint.fCoverage; 155 156 fColorFilterColor = paint.fColorFilterColor; 157 fColorFilterXfermode = paint.fColorFilterXfermode; 158 159 fColorStages = paint.fColorStages; 160 fCoverageStages = paint.fCoverageStages; 161 162 return *this; 163 } 164 165 /** 166 * Resets the paint to the defaults. 167 */ 168 void reset() { 169 this->resetBlend(); 170 this->resetOptions(); 171 this->resetColor(); 172 this->resetCoverage(); 173 this->resetStages(); 174 this->resetColorFilter(); 175 } 176 177 private: 178 /** 179 * Called when the source coord system from which geometry is rendered changes. It ensures that 180 * the local coordinates seen by effects remains unchanged. oldToNew gives the transformation 181 * from the previous coord system to the new coord system. 182 */ 183 void localCoordChange(const SkMatrix& oldToNew) { 184 for (int i = 0; i < fColorStages.count(); ++i) { 185 fColorStages[i].localCoordChange(oldToNew); 186 } 187 for (int i = 0; i < fCoverageStages.count(); ++i) { 188 fCoverageStages[i].localCoordChange(oldToNew); 189 } 190 } 191 192 bool localCoordChangeInverse(const SkMatrix& newToOld) { 193 SkMatrix oldToNew; 194 bool computed = false; 195 for (int i = 0; i < fColorStages.count(); ++i) { 196 if (!computed && !newToOld.invert(&oldToNew)) { 197 return false; 198 } else { 199 computed = true; 200 } 201 fColorStages[i].localCoordChange(oldToNew); 202 } 203 for (int i = 0; i < fCoverageStages.count(); ++i) { 204 if (!computed && !newToOld.invert(&oldToNew)) { 205 return false; 206 } else { 207 computed = true; 208 } 209 fCoverageStages[i].localCoordChange(oldToNew); 210 } 211 return true; 212 } 213 214 friend class GrContext; // To access above two functions 215 216 SkSTArray<4, GrEffectStage> fColorStages; 217 SkSTArray<2, GrEffectStage> fCoverageStages; 218 219 GrBlendCoeff fSrcBlendCoeff; 220 GrBlendCoeff fDstBlendCoeff; 221 bool fAntiAlias; 222 bool fDither; 223 224 GrColor fColor; 225 uint8_t fCoverage; 226 227 GrColor fColorFilterColor; 228 SkXfermode::Mode fColorFilterXfermode; 229 230 void resetBlend() { 231 fSrcBlendCoeff = kOne_GrBlendCoeff; 232 fDstBlendCoeff = kZero_GrBlendCoeff; 233 } 234 235 void resetOptions() { 236 fAntiAlias = false; 237 fDither = false; 238 } 239 240 void resetColor() { 241 fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff); 242 } 243 244 void resetCoverage() { 245 fCoverage = 0xff; 246 } 247 248 void resetStages() { 249 fColorStages.reset(); 250 fCoverageStages.reset(); 251 } 252 }; 253 254 #endif 255