/* * Copyright 2014 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrInvariantOutput_DEFINED #define GrInvariantOutput_DEFINED #include "GrColor.h" struct GrInitInvariantOutput { GrInitInvariantOutput() : fValidFlags(0) , fColor(0) , fIsSingleComponent(false) , fIsLCDCoverage(false) {} void setKnownFourComponents(GrColor color) { fColor = color; fValidFlags = kRGBA_GrColorComponentFlags; fIsSingleComponent = false; } void setUnknownFourComponents() { fValidFlags = 0; fIsSingleComponent = false; } void setUnknownOpaqueFourComponents() { fColor = 0xff << GrColor_SHIFT_A; fValidFlags = kA_GrColorComponentFlag; fIsSingleComponent = false; } void setKnownSingleComponent(uint8_t alpha) { fColor = GrColorPackRGBA(alpha, alpha, alpha, alpha); fValidFlags = kRGBA_GrColorComponentFlags; fIsSingleComponent = true; } void setUnknownSingleComponent() { fValidFlags = 0; fIsSingleComponent = true; } void setUsingLCDCoverage() { fIsLCDCoverage = true; } uint32_t fValidFlags; GrColor fColor; bool fIsSingleComponent; bool fIsLCDCoverage; // Temorary data member until texture pixel configs are updated }; class GrInvariantOutput { public: GrInvariantOutput(GrColor color, GrColorComponentFlags flags, bool isSingleComponent) : fColor(color) , fValidFlags(flags) , fIsSingleComponent(isSingleComponent) , fNonMulStageFound(false) , fWillUseInputColor(true) , fIsLCDCoverage(false) {} GrInvariantOutput(const GrInitInvariantOutput& io) : fColor(io.fColor) , fValidFlags(io.fValidFlags) , fIsSingleComponent(io.fIsSingleComponent) , fNonMulStageFound(false) , fWillUseInputColor(false) , fIsLCDCoverage(io.fIsLCDCoverage) {} virtual ~GrInvariantOutput() {} enum ReadInput { kWill_ReadInput, kWillNot_ReadInput, }; void mulByUnknownOpaqueFourComponents() { if (this->isOpaque()) { fValidFlags = kA_GrColorComponentFlag; fIsSingleComponent = false; } else { // Since the current state is not opaque we no longer care if the color being // multiplied is opaque. this->mulByUnknownFourComponents(); } } void mulByUnknownFourComponents() { if (this->hasZeroAlpha()) { this->internalSetToTransparentBlack(); } else { this->internalSetToUnknown(); } } void mulByUnknownSingleComponent() { if (this->hasZeroAlpha()) { this->internalSetToTransparentBlack(); } else { // We don't need to change fIsSingleComponent in this case fValidFlags = 0; } } void mulByKnownSingleComponent(uint8_t alpha) { if (this->hasZeroAlpha() || 0 == alpha) { this->internalSetToTransparentBlack(); } else { if (alpha != 255) { // Multiply color by alpha fColor = GrColorPackRGBA(SkMulDiv255Round(GrColorUnpackR(fColor), alpha), SkMulDiv255Round(GrColorUnpackG(fColor), alpha), SkMulDiv255Round(GrColorUnpackB(fColor), alpha), SkMulDiv255Round(GrColorUnpackA(fColor), alpha)); } } } void invalidateComponents(uint8_t invalidateFlags, ReadInput readsInput) { fValidFlags &= ~invalidateFlags; fIsSingleComponent = false; fNonMulStageFound = true; if (kWillNot_ReadInput == readsInput) { fWillUseInputColor = false; } } void setToOther(uint8_t validFlags, GrColor color, ReadInput readsInput) { fValidFlags = validFlags; fColor = color; fIsSingleComponent = false; fNonMulStageFound = true; if (kWillNot_ReadInput == readsInput) { fWillUseInputColor = false; } } void setToUnknown(ReadInput readsInput) { this->internalSetToUnknown(); fNonMulStageFound= true; if (kWillNot_ReadInput == readsInput) { fWillUseInputColor = false; } } // Temporary setter to handle LCD text correctly until we improve texture pixel config queries // and thus can rely solely on number of coverage components for RGA vs single channel coverage. void setUsingLCDCoverage() { fIsLCDCoverage = true; } GrColor color() const { return fColor; } uint8_t validFlags() const { return fValidFlags; } /** * If isSingleComponent is true, then the flag values for r, g, b, and a must all be the * same. If the flags are all set then all color components must be equal. */ SkDEBUGCODE(void validate() const;) private: friend class GrProcOptInfo; void reset(GrColor color, GrColorComponentFlags flags, bool isSingleComponent) { fColor = color; fValidFlags = flags; fIsSingleComponent = isSingleComponent; fNonMulStageFound = false; fWillUseInputColor = true; } void reset(const GrInitInvariantOutput& io) { fColor = io.fColor; fValidFlags = io.fValidFlags; fIsSingleComponent = io.fIsSingleComponent; fNonMulStageFound = false; fWillUseInputColor = true; fIsLCDCoverage = io.fIsLCDCoverage; } void internalSetToTransparentBlack() { fValidFlags = kRGBA_GrColorComponentFlags; fColor = 0; fIsSingleComponent = true; } void internalSetToUnknown() { fValidFlags = 0; fIsSingleComponent = false; } bool hasZeroAlpha() const { return ((fValidFlags & kA_GrColorComponentFlag) && 0 == GrColorUnpackA(fColor)); } bool isOpaque() const { return ((fValidFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(fColor)); } bool isSolidWhite() const { return (fValidFlags == kRGBA_GrColorComponentFlags && 0xFFFFFFFF == fColor); } bool isSingleComponent() const { return fIsSingleComponent; } bool willUseInputColor() const { return fWillUseInputColor; } void resetWillUseInputColor() { fWillUseInputColor = true; } void resetNonMulStageFound() { fNonMulStageFound = false; } bool isLCDCoverage() const { return fIsLCDCoverage; } SkDEBUGCODE(bool colorComponentsAllEqual() const;) /** * If alpha is valid, check that any valid R,G,B values are <= A */ SkDEBUGCODE(bool validPreMulColor() const;) GrColor fColor; uint32_t fValidFlags; bool fIsSingleComponent; bool fNonMulStageFound; bool fWillUseInputColor; bool fIsLCDCoverage; // Temorary data member until texture pixel configs are updated }; #endif