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