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