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 * Appends an additional color effect to the color computation. 89 */ 90 const GrEffectRef* addColorEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) { 91 SkASSERT(NULL != effect); 92 if (!(*effect)->willUseInputColor()) { 93 fColorStages.reset(); 94 } 95 SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect, attr0, attr1)); 96 return effect; 97 } 98 99 /** 100 * Appends an additional coverage effect to the coverage computation. 101 */ 102 const GrEffectRef* addCoverageEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) { 103 SkASSERT(NULL != effect); 104 if (!(*effect)->willUseInputColor()) { 105 fCoverageStages.reset(); 106 } 107 SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect, attr0, attr1)); 108 return effect; 109 } 110 111 /** 112 * Helpers for adding color or coverage effects that sample a texture. The matrix is applied 113 * to the src space position to compute texture coordinates. 114 */ 115 void addColorTextureEffect(GrTexture* texture, const SkMatrix& matrix); 116 void addCoverageTextureEffect(GrTexture* texture, const SkMatrix& matrix); 117 118 void addColorTextureEffect(GrTexture* texture, 119 const SkMatrix& matrix, 120 const GrTextureParams& params); 121 void addCoverageTextureEffect(GrTexture* texture, 122 const SkMatrix& matrix, 123 const GrTextureParams& params); 124 125 int numColorStages() const { return fColorStages.count(); } 126 int numCoverageStages() const { return fCoverageStages.count(); } 127 int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); } 128 129 const GrEffectStage& getColorStage(int s) const { return fColorStages[s]; } 130 const GrEffectStage& getCoverageStage(int s) const { return fCoverageStages[s]; } 131 132 GrPaint& operator=(const GrPaint& paint) { 133 fSrcBlendCoeff = paint.fSrcBlendCoeff; 134 fDstBlendCoeff = paint.fDstBlendCoeff; 135 fAntiAlias = paint.fAntiAlias; 136 fDither = paint.fDither; 137 138 fColor = paint.fColor; 139 fCoverage = paint.fCoverage; 140 141 fColorStages = paint.fColorStages; 142 fCoverageStages = paint.fCoverageStages; 143 144 return *this; 145 } 146 147 /** 148 * Resets the paint to the defaults. 149 */ 150 void reset() { 151 this->resetBlend(); 152 this->resetOptions(); 153 this->resetColor(); 154 this->resetCoverage(); 155 this->resetStages(); 156 } 157 158 /** 159 * Determines whether the drawing with this paint is opaque with respect to both color blending 160 * and fractional coverage. It does not consider whether AA has been enabled on the paint or 161 * not. Depending upon whether multisampling or coverage-based AA is in use, AA may make the 162 * result only apply to the interior of primitives. 163 * 164 */ 165 bool isOpaque() const; 166 167 /** 168 * Returns true if isOpaque would return true and the paint represents a solid constant color 169 * draw. If the result is true, constantColor will be updated to contain the constant color. 170 */ 171 bool isOpaqueAndConstantColor(GrColor* constantColor) const; 172 173 private: 174 175 /** 176 * Helper for isOpaque and isOpaqueAndConstantColor. 177 */ 178 bool getOpaqueAndKnownColor(GrColor* solidColor, uint32_t* solidColorKnownComponents) const; 179 180 /** 181 * Called when the source coord system from which geometry is rendered changes. It ensures that 182 * the local coordinates seen by effects remains unchanged. oldToNew gives the transformation 183 * from the previous coord system to the new coord system. 184 */ 185 void localCoordChange(const SkMatrix& oldToNew) { 186 for (int i = 0; i < fColorStages.count(); ++i) { 187 fColorStages[i].localCoordChange(oldToNew); 188 } 189 for (int i = 0; i < fCoverageStages.count(); ++i) { 190 fCoverageStages[i].localCoordChange(oldToNew); 191 } 192 } 193 194 bool localCoordChangeInverse(const SkMatrix& newToOld) { 195 SkMatrix oldToNew; 196 bool computed = false; 197 for (int i = 0; i < fColorStages.count(); ++i) { 198 if (!computed && !newToOld.invert(&oldToNew)) { 199 return false; 200 } else { 201 computed = true; 202 } 203 fColorStages[i].localCoordChange(oldToNew); 204 } 205 for (int i = 0; i < fCoverageStages.count(); ++i) { 206 if (!computed && !newToOld.invert(&oldToNew)) { 207 return false; 208 } else { 209 computed = true; 210 } 211 fCoverageStages[i].localCoordChange(oldToNew); 212 } 213 return true; 214 } 215 216 friend class GrContext; // To access above two functions 217 218 SkSTArray<4, GrEffectStage> fColorStages; 219 SkSTArray<2, GrEffectStage> fCoverageStages; 220 221 GrBlendCoeff fSrcBlendCoeff; 222 GrBlendCoeff fDstBlendCoeff; 223 bool fAntiAlias; 224 bool fDither; 225 226 GrColor fColor; 227 uint8_t fCoverage; 228 229 void resetBlend() { 230 fSrcBlendCoeff = kOne_GrBlendCoeff; 231 fDstBlendCoeff = kZero_GrBlendCoeff; 232 } 233 234 void resetOptions() { 235 fAntiAlias = false; 236 fDither = false; 237 } 238 239 void resetColor() { 240 fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff); 241 } 242 243 void resetCoverage() { 244 fCoverage = 0xff; 245 } 246 247 void resetStages() { 248 fColorStages.reset(); 249 fCoverageStages.reset(); 250 } 251 }; 252 253 #endif 254