Home | History | Annotate | Download | only in gpu
      1 /*
      2 * Copyright 2015 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 #include "GrBlend.h"
      9 
     10 /**
     11  * MaskedColor is used to evaluate the color and valid color component flags through the
     12  * blending equation. Could possibly extend this to be used more broadly.
     13  */
     14 class MaskedColor {
     15 public:
     16     MaskedColor(GrColor color, GrColorComponentFlags flags)
     17         : fColor(color)
     18         , fFlags(flags) {}
     19 
     20     MaskedColor() {}
     21 
     22     void set(GrColor color, GrColorComponentFlags flags) {
     23         fColor = color;
     24         fFlags = flags;
     25     }
     26 
     27     static MaskedColor Invert(const MaskedColor& in) {
     28         return MaskedColor(GrInvertColor(in.fColor), in.fFlags);
     29     }
     30 
     31     static MaskedColor ExtractAlpha(const MaskedColor& in) {
     32         GrColorComponentFlags flags = (in.fFlags & kA_GrColorComponentFlag) ?
     33             kRGBA_GrColorComponentFlags : kNone_GrColorComponentFlags;
     34         return MaskedColor(GrColorPackA4(GrColorUnpackA(in.fColor)), flags);
     35     }
     36 
     37     static MaskedColor ExtractInverseAlpha(const MaskedColor& in) {
     38         GrColorComponentFlags flags = (in.fFlags & kA_GrColorComponentFlag) ?
     39             kRGBA_GrColorComponentFlags : kNone_GrColorComponentFlags;
     40         return MaskedColor(GrColorPackA4(0xFF - GrColorUnpackA(in.fColor)), flags);
     41     }
     42 
     43     static MaskedColor Mul(const MaskedColor& a, const MaskedColor& b) {
     44         GrColorComponentFlags outFlags = (a.fFlags & b.fFlags) | a.componentsWithValue(0) |
     45                                          b.componentsWithValue(0);
     46         return MaskedColor(GrColorMul(a.fColor, b.fColor), outFlags);
     47     }
     48 
     49     static MaskedColor SatAdd(const MaskedColor& a, const MaskedColor& b) {
     50         GrColorComponentFlags outFlags = (a.fFlags & b.fFlags) | a.componentsWithValue(0xFF) |
     51                                          b.componentsWithValue(0xFF);
     52         return MaskedColor(GrColorSatAdd(a.fColor, b.fColor), outFlags);
     53     }
     54 
     55     GrColor color() const { return fColor; }
     56 
     57     GrColorComponentFlags validFlags () const { return fFlags; }
     58 
     59 private:
     60     GrColorComponentFlags componentsWithValue(unsigned value) const {
     61         GrColorComponentFlags flags = kNone_GrColorComponentFlags;
     62         if ((kR_GrColorComponentFlag & fFlags) && value == GrColorUnpackR(fColor)) {
     63             flags |= kR_GrColorComponentFlag;
     64         }
     65         if ((kG_GrColorComponentFlag & fFlags) && value == GrColorUnpackG(fColor)) {
     66             flags |= kG_GrColorComponentFlag;
     67         }
     68         if ((kB_GrColorComponentFlag & fFlags) && value == GrColorUnpackB(fColor)) {
     69             flags |= kB_GrColorComponentFlag;
     70         }
     71         if ((kA_GrColorComponentFlag & fFlags) && value == GrColorUnpackA(fColor)) {
     72             flags |= kA_GrColorComponentFlag;
     73         }
     74         return flags;
     75     }
     76 
     77     GrColor                 fColor;
     78     GrColorComponentFlags   fFlags;
     79 };
     80 
     81 static MaskedColor get_term(GrBlendCoeff coeff, const MaskedColor& src, const MaskedColor& dst,
     82                             const MaskedColor& value) {
     83     switch (coeff) {
     84         case kZero_GrBlendCoeff:
     85             return MaskedColor(0, kRGBA_GrColorComponentFlags);
     86         case kOne_GrBlendCoeff:
     87             return value;
     88         case kDC_GrBlendCoeff:
     89             return MaskedColor::Mul(dst, value);
     90         case kIDC_GrBlendCoeff:
     91             return MaskedColor::Mul(MaskedColor::Invert(dst), value);
     92         case kDA_GrBlendCoeff:
     93             return MaskedColor::Mul(MaskedColor::ExtractAlpha(dst), value);
     94         case kIDA_GrBlendCoeff:
     95             return MaskedColor::Mul(MaskedColor::ExtractInverseAlpha(dst), value);
     96         case kSC_GrBlendCoeff:
     97             return MaskedColor::Mul(src, value);
     98         case kISC_GrBlendCoeff:
     99             return MaskedColor::Mul(MaskedColor::Invert(src), value);
    100         case kSA_GrBlendCoeff:
    101             return MaskedColor::Mul(MaskedColor::ExtractAlpha(src), value);
    102         case kISA_GrBlendCoeff:
    103             return MaskedColor::Mul(MaskedColor::ExtractInverseAlpha(src), value);
    104         default:
    105             SK_ABORT("Illegal coefficient");
    106             return MaskedColor();
    107     }
    108 }
    109 
    110 void GrGetCoeffBlendKnownComponents(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff,
    111                                     GrColor srcColor, GrColorComponentFlags srcColorFlags,
    112                                     GrColor dstColor, GrColorComponentFlags dstColorFlags,
    113                                     GrColor* outColor,
    114                                     GrColorComponentFlags* outFlags) {
    115     MaskedColor src(srcColor, srcColorFlags);
    116     MaskedColor dst(dstColor, dstColorFlags);
    117 
    118     MaskedColor srcTerm = get_term(srcCoeff, src, dst, src);
    119     MaskedColor dstTerm = get_term(dstCoeff, src, dst, dst);
    120 
    121     MaskedColor output = MaskedColor::SatAdd(srcTerm, dstTerm);
    122     *outColor = output.color();
    123     *outFlags = output.validFlags();
    124 }
    125