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(0)
     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 = 0;
     28         fIsSingleComponent = false;
     29     }
     30 
     31     void setUnknownOpaqueFourComponents() {
     32         fColor = 0xff << 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 = 0;
     45         fIsSingleComponent = true;
     46     }
     47 
     48     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:
     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 
     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 
     74     virtual ~GrInvariantOutput() {}
     75 
     76     enum ReadInput {
     77         kWill_ReadInput,
     78         kWillNot_ReadInput,
     79     };
     80 
     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 
     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 
    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 
    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 
    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.
    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.
    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 
    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 
    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 
    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.
    245     void setUsingLCDCoverage() {
    246         fIsLCDCoverage = true;
    247     }
    248 
    249     GrColor color() const { return fColor; }
    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. */
    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 
    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 
    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 
    285     void internalSetToTransparentBlack() {
    286         fValidFlags = kRGBA_GrColorComponentFlags;
    287         fColor = 0;
    288         fIsSingleComponent = true;
    289     }
    290 
    291     void internalSetToUnknown() {
    292         fValidFlags = 0;
    293         fIsSingleComponent = false;
    294     }
    295 
    296     bool hasZeroAlpha() const {
    297         return ((fValidFlags & kA_GrColorComponentFlag) && 0 == GrColorUnpackA(fColor));
    298     }
    299 
    300     bool isOpaque() const {
    301         return ((fValidFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(fColor));
    302     }
    303 
    304     bool isSolidWhite() const {
    305         return (fValidFlags == kRGBA_GrColorComponentFlags && 0xFFFFFFFF == fColor);
    306     }
    307 
    308     bool isSingleComponent() const { return fIsSingleComponent; }
    309 
    310     bool willUseInputColor() const { return fWillUseInputColor; }
    311     void resetWillUseInputColor() { fWillUseInputColor = true; }
    312 
    313     bool allStagesMulInput() const { return !fNonMulStageFound; }
    314     void resetNonMulStageFound() { fNonMulStageFound = false; }
    315 
    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