Home | History | Annotate | Download | only in gpu
      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