1 /* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrInvariantOutput_DEFINED 9 #define GrInvariantOutput_DEFINED 10 11 #include "GrColor.h" 12 13 struct GrInitInvariantOutput { 14 GrInitInvariantOutput() 15 : fValidFlags(kNone_GrColorComponentFlags) 16 , fColor(0) 17 , fIsSingleComponent(false) 18 , fIsLCDCoverage(false) {} 19 20 void setKnownFourComponents(GrColor color) { 21 fColor = color; 22 fValidFlags = kRGBA_GrColorComponentFlags; 23 fIsSingleComponent = false; 24 } 25 26 void setUnknownFourComponents() { 27 fValidFlags = kNone_GrColorComponentFlags; 28 fIsSingleComponent = false; 29 } 30 31 void setUnknownOpaqueFourComponents() { 32 fColor = 0xffU << GrColor_SHIFT_A; 33 fValidFlags = kA_GrColorComponentFlag; 34 fIsSingleComponent = false; 35 } 36 37 void setKnownSingleComponent(uint8_t alpha) { 38 fColor = GrColorPackRGBA(alpha, alpha, alpha, alpha); 39 fValidFlags = kRGBA_GrColorComponentFlags; 40 fIsSingleComponent = true; 41 } 42 43 void setUnknownSingleComponent() { 44 fValidFlags = kNone_GrColorComponentFlags; 45 fIsSingleComponent = true; 46 } 47 48 void setUsingLCDCoverage() { fIsLCDCoverage = true; } 49 50 GrColorComponentFlags fValidFlags; 51 GrColor fColor; 52 bool fIsSingleComponent; 53 bool fIsLCDCoverage; // Temorary data member until texture pixel configs are 54 // updated 55 }; 56 57 class GrInvariantOutput { 58 public: 59 GrInvariantOutput(GrColor color, GrColorComponentFlags flags, bool isSingleComponent) 60 : fColor(color) 61 , fValidFlags(flags) 62 , fIsSingleComponent(isSingleComponent) 63 , fNonMulStageFound(false) 64 , fWillUseInputColor(true) 65 , fIsLCDCoverage(false) {} 66 67 GrInvariantOutput(const GrInitInvariantOutput& io) 68 : fColor(io.fColor) 69 , fValidFlags(io.fValidFlags) 70 , fIsSingleComponent(io.fIsSingleComponent) 71 , fNonMulStageFound(false) 72 , fWillUseInputColor(false) 73 , fIsLCDCoverage(io.fIsLCDCoverage) {} 74 75 virtual ~GrInvariantOutput() {} 76 77 enum ReadInput { 78 kWill_ReadInput, 79 kWillNot_ReadInput, 80 }; 81 82 void mulByUnknownOpaqueFourComponents() { 83 SkDEBUGCODE(this->validate()); 84 if (this->isOpaque()) { 85 fValidFlags = kA_GrColorComponentFlag; 86 fIsSingleComponent = false; 87 } else { 88 // Since the current state is not opaque we no longer care if the color being 89 // multiplied is opaque. 90 this->mulByUnknownFourComponents(); 91 } 92 SkDEBUGCODE(this->validate()); 93 } 94 95 void mulByUnknownFourComponents() { 96 SkDEBUGCODE(this->validate()); 97 if (this->hasZeroAlpha()) { 98 this->internalSetToTransparentBlack(); 99 } else { 100 this->internalSetToUnknown(); 101 } 102 SkDEBUGCODE(this->validate()); 103 } 104 105 void mulByUnknownSingleComponent() { 106 SkDEBUGCODE(this->validate()); 107 if (this->hasZeroAlpha()) { 108 this->internalSetToTransparentBlack(); 109 } else { 110 // We don't need to change fIsSingleComponent in this case 111 fValidFlags = kNone_GrColorComponentFlags; 112 } 113 SkDEBUGCODE(this->validate()); 114 } 115 116 void mulByKnownSingleComponent(uint8_t alpha) { 117 SkDEBUGCODE(this->validate()); 118 if (this->hasZeroAlpha() || 0 == alpha) { 119 this->internalSetToTransparentBlack(); 120 } else { 121 if (alpha != 255) { 122 // Multiply color by alpha 123 fColor = GrColorPackRGBA(SkMulDiv255Round(GrColorUnpackR(fColor), alpha), 124 SkMulDiv255Round(GrColorUnpackG(fColor), alpha), 125 SkMulDiv255Round(GrColorUnpackB(fColor), alpha), 126 SkMulDiv255Round(GrColorUnpackA(fColor), alpha)); 127 // We don't need to change fIsSingleComponent in this case 128 } 129 } 130 SkDEBUGCODE(this->validate()); 131 } 132 133 void mulByKnownFourComponents(GrColor color) { 134 SkDEBUGCODE(this->validate()); 135 uint32_t a; 136 if (GetAlphaAndCheckSingleChannel(color, &a)) { 137 this->mulByKnownSingleComponent(a); 138 } else { 139 if (color != 0xffffffff) { 140 fColor = GrColorPackRGBA( 141 SkMulDiv255Round(GrColorUnpackR(fColor), GrColorUnpackR(color)), 142 SkMulDiv255Round(GrColorUnpackG(fColor), GrColorUnpackG(color)), 143 SkMulDiv255Round(GrColorUnpackB(fColor), GrColorUnpackB(color)), 144 SkMulDiv255Round(GrColorUnpackA(fColor), a)); 145 if (kRGBA_GrColorComponentFlags == fValidFlags) { 146 fIsSingleComponent = GetAlphaAndCheckSingleChannel(fColor, &a); 147 } 148 } 149 } 150 SkDEBUGCODE(this->validate()); 151 } 152 153 // Ignores the incoming color's RGB and muls its alpha by color. 154 void mulAlphaByKnownFourComponents(GrColor color) { 155 SkDEBUGCODE(this->validate()); 156 uint32_t a; 157 if (GetAlphaAndCheckSingleChannel(color, &a)) { 158 this->mulAlphaByKnownSingleComponent(a); 159 } else if (fValidFlags & kA_GrColorComponentFlag) { 160 GrColor preAlpha = GrColorUnpackA(fColor); 161 if (0 == preAlpha) { 162 this->internalSetToTransparentBlack(); 163 } else { 164 // We know that color has different component values 165 fIsSingleComponent = false; 166 fColor = GrColorPackRGBA( 167 SkMulDiv255Round(preAlpha, GrColorUnpackR(color)), 168 SkMulDiv255Round(preAlpha, GrColorUnpackG(color)), 169 SkMulDiv255Round(preAlpha, GrColorUnpackB(color)), 170 SkMulDiv255Round(preAlpha, a)); 171 fValidFlags = kRGBA_GrColorComponentFlags; 172 } 173 } else { 174 fIsSingleComponent = false; 175 fValidFlags = kNone_GrColorComponentFlags; 176 } 177 SkDEBUGCODE(this->validate()); 178 } 179 180 // Ignores the incoming color's RGB and muls its alpha by the alpha param and sets all channels 181 // equal to that value. 182 void mulAlphaByKnownSingleComponent(uint8_t alpha) { 183 SkDEBUGCODE(this->validate()); 184 if (0 == alpha || this->hasZeroAlpha()) { 185 this->internalSetToTransparentBlack(); 186 } else { 187 if (fValidFlags & kA_GrColorComponentFlag) { 188 GrColor a = GrColorUnpackA(fColor); 189 a = SkMulDiv255Round(alpha, a); 190 fColor = GrColorPackRGBA(a, a, a, a); 191 fValidFlags = kRGBA_GrColorComponentFlags; 192 } else { 193 fValidFlags = kNone_GrColorComponentFlags; 194 } 195 fIsSingleComponent = true; 196 } 197 SkDEBUGCODE(this->validate()); 198 } 199 200 void invalidateComponents(GrColorComponentFlags invalidateFlags, ReadInput readsInput) { 201 SkDEBUGCODE(this->validate()); 202 fValidFlags = (fValidFlags & ~invalidateFlags); 203 fIsSingleComponent = false; 204 fNonMulStageFound = true; 205 if (kWillNot_ReadInput == readsInput) { 206 fWillUseInputColor = false; 207 } 208 SkDEBUGCODE(this->validate()); 209 } 210 211 void setToOther(GrColorComponentFlags validFlags, GrColor color, ReadInput readsInput) { 212 SkDEBUGCODE(this->validate()); 213 fValidFlags = validFlags; 214 fColor = color; 215 fIsSingleComponent = false; 216 fNonMulStageFound = true; 217 if (kWillNot_ReadInput == readsInput) { 218 fWillUseInputColor = false; 219 } 220 if (kRGBA_GrColorComponentFlags == fValidFlags) { 221 uint32_t a; 222 if (GetAlphaAndCheckSingleChannel(color, &a)) { 223 fIsSingleComponent = true; 224 } 225 } 226 SkDEBUGCODE(this->validate()); 227 } 228 229 void setToUnknown(ReadInput readsInput) { 230 SkDEBUGCODE(this->validate()); 231 this->internalSetToUnknown(); 232 fNonMulStageFound= true; 233 if (kWillNot_ReadInput == readsInput) { 234 fWillUseInputColor = false; 235 } 236 SkDEBUGCODE(this->validate()); 237 } 238 239 // Temporary setter to handle LCD text correctly until we improve texture pixel config queries 240 // and thus can rely solely on number of coverage components for RGA vs single channel coverage. 241 void setUsingLCDCoverage() { 242 fIsLCDCoverage = true; 243 } 244 245 GrColor color() const { return fColor; } 246 GrColorComponentFlags validFlags() const { return fValidFlags; } 247 bool willUseInputColor() const { return fWillUseInputColor; } 248 249 /** 250 * If isSingleComponent is true, then the flag values for r, g, b, and a must all be the 251 * same. If the flags are all set then all color components must be equal. 252 */ 253 SkDEBUGCODE(void validate() const;) 254 255 private: 256 friend class GrProcOptInfo; 257 258 /** Extracts the alpha channel and returns true if r,g,b == a. */ 259 static bool GetAlphaAndCheckSingleChannel(GrColor color, uint32_t* alpha) { 260 *alpha = GrColorUnpackA(color); 261 return *alpha == GrColorUnpackR(color) && *alpha == GrColorUnpackG(color) && 262 *alpha == GrColorUnpackB(color); 263 } 264 265 void reset(GrColor color, GrColorComponentFlags flags, bool isSingleComponent) { 266 fColor = color; 267 fValidFlags = flags; 268 fIsSingleComponent = isSingleComponent; 269 fNonMulStageFound = false; 270 fWillUseInputColor = true; 271 } 272 273 void reset(const GrInitInvariantOutput& io) { 274 fColor = io.fColor; 275 fValidFlags = io.fValidFlags; 276 fIsSingleComponent = io.fIsSingleComponent; 277 fNonMulStageFound = false; 278 fWillUseInputColor = true; 279 fIsLCDCoverage = io.fIsLCDCoverage; 280 } 281 282 void internalSetToTransparentBlack() { 283 fValidFlags = kRGBA_GrColorComponentFlags; 284 fColor = 0; 285 fIsSingleComponent = true; 286 } 287 288 void internalSetToUnknown() { 289 fValidFlags = kNone_GrColorComponentFlags; 290 fIsSingleComponent = false; 291 } 292 293 bool hasZeroAlpha() const { 294 return ((fValidFlags & kA_GrColorComponentFlag) && 0 == GrColorUnpackA(fColor)); 295 } 296 297 bool isOpaque() const { 298 return ((fValidFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(fColor)); 299 } 300 301 bool isSolidWhite() const { 302 return (fValidFlags == kRGBA_GrColorComponentFlags && 0xFFFFFFFF == fColor); 303 } 304 305 bool isSingleComponent() const { return fIsSingleComponent; } 306 307 void resetWillUseInputColor() { fWillUseInputColor = true; } 308 309 bool allStagesMulInput() const { return !fNonMulStageFound; } 310 void resetNonMulStageFound() { fNonMulStageFound = false; } 311 312 bool isLCDCoverage() const { return fIsLCDCoverage; } 313 314 SkDEBUGCODE(bool colorComponentsAllEqual() const;) 315 /** 316 * If alpha is valid, check that any valid R,G,B values are <= A 317 */ 318 SkDEBUGCODE(bool validPreMulColor() const;) 319 320 GrColor fColor; 321 GrColorComponentFlags fValidFlags; 322 bool fIsSingleComponent; 323 bool fNonMulStageFound; 324 bool fWillUseInputColor; 325 bool fIsLCDCoverage; // Temorary data member until texture pixel configs are updated 326 327 }; 328 329 #endif 330 331