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 enum { 47 kMaxColorStages = 2, 48 kMaxCoverageStages = 1, 49 }; 50 GrPaint()51 GrPaint() { this->reset(); } 52 GrPaint(const GrPaint & paint)53 GrPaint(const GrPaint& paint) { *this = paint; } 54 ~GrPaint()55 ~GrPaint() {} 56 57 /** 58 * Sets the blending coefficients to use to blend the final primitive color with the 59 * destination color. Defaults to kOne for src and kZero for dst (i.e. src mode). 60 */ setBlendFunc(GrBlendCoeff srcCoeff,GrBlendCoeff dstCoeff)61 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 62 fSrcBlendCoeff = srcCoeff; 63 fDstBlendCoeff = dstCoeff; 64 } getSrcBlendCoeff()65 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlendCoeff; } getDstBlendCoeff()66 GrBlendCoeff getDstBlendCoeff() const { return fDstBlendCoeff; } 67 68 /** 69 * The initial color of the drawn primitive. Defaults to solid white. 70 */ setColor(GrColor color)71 void setColor(GrColor color) { fColor = color; } getColor()72 GrColor getColor() const { return fColor; } 73 74 /** 75 * Applies fractional coverage to the entire drawn primitive. Defaults to 0xff. 76 */ setCoverage(uint8_t coverage)77 void setCoverage(uint8_t coverage) { fCoverage = coverage; } getCoverage()78 uint8_t getCoverage() const { return fCoverage; } 79 80 /** 81 * Should primitives be anti-aliased or not. Defaults to false. 82 */ setAntiAlias(bool aa)83 void setAntiAlias(bool aa) { fAntiAlias = aa; } isAntiAlias()84 bool isAntiAlias() const { return fAntiAlias; } 85 86 /** 87 * Should dithering be applied. Defaults to false. 88 */ setDither(bool dither)89 void setDither(bool dither) { fDither = dither; } isDither()90 bool isDither() const { return fDither; } 91 92 /** 93 * Enables a SkXfermode::Mode-based color filter applied to the primitive color. The constant 94 * color passed to this function is considered the "src" color and the primitive's color is 95 * considered the "dst" color. Defaults to kDst_Mode which equates to simply passing through 96 * the primitive color unmodified. 97 */ setXfermodeColorFilter(SkXfermode::Mode mode,GrColor color)98 void setXfermodeColorFilter(SkXfermode::Mode mode, GrColor color) { 99 fColorFilterColor = color; 100 fColorFilterXfermode = mode; 101 } getColorFilterMode()102 SkXfermode::Mode getColorFilterMode() const { return fColorFilterXfermode; } getColorFilterColor()103 GrColor getColorFilterColor() const { return fColorFilterColor; } 104 105 /** 106 * Disables the SkXfermode::Mode color filter. 107 */ resetColorFilter()108 void resetColorFilter() { 109 fColorFilterXfermode = SkXfermode::kDst_Mode; 110 fColorFilterColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff); 111 } 112 113 /** 114 * Specifies a stage of the color pipeline. Usually the texture matrices of color stages apply 115 * to the primitive's positions. Some GrContext calls take explicit coords as an array or a 116 * rect. In this case these are the pre-matrix coords to colorStage(0). 117 */ colorStage(int i)118 GrEffectStage* colorStage(int i) { 119 GrAssert((unsigned)i < kMaxColorStages); 120 return fColorStages + i; 121 } 122 getColorStage(int i)123 const GrEffectStage& getColorStage(int i) const { 124 GrAssert((unsigned)i < kMaxColorStages); 125 return fColorStages[i]; 126 } 127 isColorStageEnabled(int i)128 bool isColorStageEnabled(int i) const { 129 GrAssert((unsigned)i < kMaxColorStages); 130 return (NULL != fColorStages[i].getEffect()); 131 } 132 133 /** 134 * Specifies a stage of the coverage pipeline. Coverage stages' texture matrices are always 135 * applied to the primitive's position, never to explicit texture coords. 136 */ coverageStage(int i)137 GrEffectStage* coverageStage(int i) { 138 GrAssert((unsigned)i < kMaxCoverageStages); 139 return fCoverageStages + i; 140 } 141 getCoverageStage(int i)142 const GrEffectStage& getCoverageStage(int i) const { 143 GrAssert((unsigned)i < kMaxCoverageStages); 144 return fCoverageStages[i]; 145 } 146 isCoverageStageEnabled(int i)147 bool isCoverageStageEnabled(int i) const { 148 GrAssert((unsigned)i < kMaxCoverageStages); 149 return (NULL != fCoverageStages[i].getEffect()); 150 } 151 hasCoverageStage()152 bool hasCoverageStage() const { 153 for (int i = 0; i < kMaxCoverageStages; ++i) { 154 if (this->isCoverageStageEnabled(i)) { 155 return true; 156 } 157 } 158 return false; 159 } 160 hasColorStage()161 bool hasColorStage() const { 162 for (int i = 0; i < kMaxColorStages; ++i) { 163 if (this->isColorStageEnabled(i)) { 164 return true; 165 } 166 } 167 return false; 168 } 169 hasStage()170 bool hasStage() const { return this->hasColorStage() || this->hasCoverageStage(); } 171 172 /** 173 * Called when the source coord system is changing. preConcatInverse is the inverse of the 174 * transformation from the old coord system to the new coord system. Returns false if the matrix 175 * cannot be inverted. 176 */ sourceCoordChangeByInverse(const SkMatrix & preConcatInverse)177 bool sourceCoordChangeByInverse(const SkMatrix& preConcatInverse) { 178 SkMatrix inv; 179 bool computed = false; 180 for (int i = 0; i < kMaxColorStages; ++i) { 181 if (this->isColorStageEnabled(i)) { 182 if (!computed && !preConcatInverse.invert(&inv)) { 183 return false; 184 } else { 185 computed = true; 186 } 187 fColorStages[i].preConcatCoordChange(inv); 188 } 189 } 190 for (int i = 0; i < kMaxCoverageStages; ++i) { 191 if (this->isCoverageStageEnabled(i)) { 192 if (!computed && !preConcatInverse.invert(&inv)) { 193 return false; 194 } else { 195 computed = true; 196 } 197 fCoverageStages[i].preConcatCoordChange(inv); 198 } 199 } 200 return true; 201 } 202 203 /** 204 * Called when the source coord system is changing. preConcat gives the transformation from the 205 * old coord system to the new coord system. 206 */ sourceCoordChange(const SkMatrix & preConcat)207 void sourceCoordChange(const SkMatrix& preConcat) { 208 for (int i = 0; i < kMaxColorStages; ++i) { 209 if (this->isColorStageEnabled(i)) { 210 fColorStages[i].preConcatCoordChange(preConcat); 211 } 212 } 213 for (int i = 0; i < kMaxCoverageStages; ++i) { 214 if (this->isCoverageStageEnabled(i)) { 215 fCoverageStages[i].preConcatCoordChange(preConcat); 216 } 217 } 218 } 219 220 GrPaint& operator=(const GrPaint& paint) { 221 fSrcBlendCoeff = paint.fSrcBlendCoeff; 222 fDstBlendCoeff = paint.fDstBlendCoeff; 223 fAntiAlias = paint.fAntiAlias; 224 fDither = paint.fDither; 225 226 fColor = paint.fColor; 227 fCoverage = paint.fCoverage; 228 229 fColorFilterColor = paint.fColorFilterColor; 230 fColorFilterXfermode = paint.fColorFilterXfermode; 231 232 for (int i = 0; i < kMaxColorStages; ++i) { 233 if (paint.isColorStageEnabled(i)) { 234 fColorStages[i] = paint.fColorStages[i]; 235 } 236 } 237 for (int i = 0; i < kMaxCoverageStages; ++i) { 238 if (paint.isCoverageStageEnabled(i)) { 239 fCoverageStages[i] = paint.fCoverageStages[i]; 240 } 241 } 242 return *this; 243 } 244 245 /** 246 * Resets the paint to the defaults. 247 */ reset()248 void reset() { 249 this->resetBlend(); 250 this->resetOptions(); 251 this->resetColor(); 252 this->resetCoverage(); 253 this->resetStages(); 254 this->resetColorFilter(); 255 } 256 257 // internal use 258 // GrPaint's textures and masks map to the first N stages 259 // of GrDrawTarget in that order (textures followed by masks) 260 enum { 261 kFirstColorStage = 0, 262 kFirstCoverageStage = kMaxColorStages, 263 kTotalStages = kFirstColorStage + kMaxColorStages + kMaxCoverageStages, 264 }; 265 266 private: 267 268 GrEffectStage fColorStages[kMaxColorStages]; 269 GrEffectStage fCoverageStages[kMaxCoverageStages]; 270 271 GrBlendCoeff fSrcBlendCoeff; 272 GrBlendCoeff fDstBlendCoeff; 273 bool fAntiAlias; 274 bool fDither; 275 276 GrColor fColor; 277 uint8_t fCoverage; 278 279 GrColor fColorFilterColor; 280 SkXfermode::Mode fColorFilterXfermode; 281 resetBlend()282 void resetBlend() { 283 fSrcBlendCoeff = kOne_GrBlendCoeff; 284 fDstBlendCoeff = kZero_GrBlendCoeff; 285 } 286 resetOptions()287 void resetOptions() { 288 fAntiAlias = false; 289 fDither = false; 290 } 291 resetColor()292 void resetColor() { 293 fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff); 294 } 295 resetCoverage()296 void resetCoverage() { 297 fCoverage = 0xff; 298 } 299 resetStages()300 void resetStages() { 301 for (int i = 0; i < kMaxColorStages; ++i) { 302 fColorStages[i].reset(); 303 } 304 for (int i = 0; i < kMaxCoverageStages; ++i) { 305 fCoverageStages[i].reset(); 306 } 307 } 308 }; 309 310 #endif 311