Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3  * Copyright 2013 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "GrBlend.h"
     10 
     11 static inline GrBlendCoeff swap_coeff_src_dst(GrBlendCoeff coeff) {
     12     switch (coeff) {
     13         case kDC_GrBlendCoeff:
     14             return kSC_GrBlendCoeff;
     15         case kIDC_GrBlendCoeff:
     16             return kISC_GrBlendCoeff;
     17         case kDA_GrBlendCoeff:
     18             return kSA_GrBlendCoeff;
     19         case kIDA_GrBlendCoeff:
     20             return kISA_GrBlendCoeff;
     21         case kSC_GrBlendCoeff:
     22             return kDC_GrBlendCoeff;
     23         case kISC_GrBlendCoeff:
     24             return kIDC_GrBlendCoeff;
     25         case kSA_GrBlendCoeff:
     26             return kDA_GrBlendCoeff;
     27         case kISA_GrBlendCoeff:
     28             return kIDA_GrBlendCoeff;
     29         default:
     30             return coeff;
     31     }
     32 }
     33 
     34 static inline unsigned saturated_add(unsigned a, unsigned b) {
     35     SkASSERT(a <= 255);
     36     SkASSERT(b <= 255);
     37     unsigned sum = a + b;
     38     if (sum > 255) {
     39         sum = 255;
     40     }
     41     return sum;
     42 }
     43 
     44 static GrColor add_colors(GrColor src, GrColor dst) {
     45     unsigned r = saturated_add(GrColorUnpackR(src), GrColorUnpackR(dst));
     46     unsigned g = saturated_add(GrColorUnpackG(src), GrColorUnpackG(dst));
     47     unsigned b = saturated_add(GrColorUnpackB(src), GrColorUnpackB(dst));
     48     unsigned a = saturated_add(GrColorUnpackA(src), GrColorUnpackA(dst));
     49     return GrColorPackRGBA(r, g, b, a);
     50 }
     51 
     52 static inline bool valid_color(uint32_t compFlags) {
     53      return (kRGBA_GrColorComponentFlags & compFlags) == kRGBA_GrColorComponentFlags;
     54 }
     55 
     56 static GrColor simplify_blend_term(GrBlendCoeff* srcCoeff,
     57                                    GrColor srcColor, uint32_t srcCompFlags,
     58                                    GrColor dstColor, uint32_t dstCompFlags,
     59                                    GrColor constantColor) {
     60 
     61     SkASSERT(!GrBlendCoeffRefsSrc(*srcCoeff));
     62     SkASSERT(srcCoeff);
     63 
     64     // Check whether srcCoeff can be reduced to kOne or kZero based on known color inputs.
     65     // We could pick out the coeff r,g,b,a values here and use them to compute the blend term color,
     66     // if possible, below but that is not implemented now.
     67     switch (*srcCoeff) {
     68         case kIDC_GrBlendCoeff:
     69             dstColor = ~dstColor; // fallthrough
     70         case kDC_GrBlendCoeff:
     71             if (valid_color(dstCompFlags)) {
     72                 if (0xffffffff == dstColor) {
     73                     *srcCoeff = kOne_GrBlendCoeff;
     74                 } else if (0 == dstColor) {
     75                     *srcCoeff = kZero_GrBlendCoeff;
     76                 }
     77             }
     78             break;
     79 
     80         case kIDA_GrBlendCoeff:
     81             dstColor = ~dstColor; // fallthrough
     82         case kDA_GrBlendCoeff:
     83             if (kA_GrColorComponentFlag & dstCompFlags) {
     84                 if (0xff == GrColorUnpackA(dstColor)) {
     85                     *srcCoeff = kOne_GrBlendCoeff;
     86                 } else if (0 == GrColorUnpackA(dstColor)) {
     87                     *srcCoeff = kZero_GrBlendCoeff;
     88                 }
     89             }
     90             break;
     91 
     92         case kIConstC_GrBlendCoeff:
     93             constantColor = ~constantColor; // fallthrough
     94         case kConstC_GrBlendCoeff:
     95             if (0xffffffff == constantColor) {
     96                 *srcCoeff = kOne_GrBlendCoeff;
     97             } else if (0 == constantColor) {
     98                 *srcCoeff = kZero_GrBlendCoeff;
     99             }
    100             break;
    101 
    102         case kIConstA_GrBlendCoeff:
    103             constantColor = ~constantColor; // fallthrough
    104         case kConstA_GrBlendCoeff:
    105             if (0xff == GrColorUnpackA(constantColor)) {
    106                 *srcCoeff = kOne_GrBlendCoeff;
    107             } else if (0 == GrColorUnpackA(constantColor)) {
    108                 *srcCoeff = kZero_GrBlendCoeff;
    109             }
    110             break;
    111 
    112         default:
    113             break;
    114     }
    115     // We may have invalidated these above and shouldn't read them again.
    116     SkDEBUGCODE(dstColor = constantColor = GrColor_ILLEGAL;)
    117 
    118     if (kZero_GrBlendCoeff == *srcCoeff || (valid_color(srcCompFlags) && 0 == srcColor)) {
    119         *srcCoeff = kZero_GrBlendCoeff;
    120         return 0;
    121     }
    122 
    123     if (kOne_GrBlendCoeff == *srcCoeff && valid_color(srcCompFlags)) {
    124         return srcColor;
    125     } else {
    126         return GrColor_ILLEGAL;
    127     }
    128 }
    129 
    130 GrColor GrSimplifyBlend(GrBlendCoeff* srcCoeff,
    131                         GrBlendCoeff* dstCoeff,
    132                         GrColor srcColor, uint32_t srcCompFlags,
    133                         GrColor dstColor, uint32_t dstCompFlags,
    134                         GrColor constantColor) {
    135     GrColor srcTermColor = simplify_blend_term(srcCoeff,
    136                                                srcColor, srcCompFlags,
    137                                                dstColor, dstCompFlags,
    138                                                constantColor);
    139 
    140     // We call the same function to simplify the dst blend coeff. We trick it out by swapping the
    141     // src and dst.
    142     GrBlendCoeff spoofedCoeff = swap_coeff_src_dst(*dstCoeff);
    143     GrColor dstTermColor = simplify_blend_term(&spoofedCoeff,
    144                                                dstColor, dstCompFlags,
    145                                                srcColor, srcCompFlags,
    146                                                constantColor);
    147     *dstCoeff = swap_coeff_src_dst(spoofedCoeff);
    148 
    149     if (GrColor_ILLEGAL != srcTermColor && GrColor_ILLEGAL != dstTermColor) {
    150         return add_colors(srcTermColor, dstTermColor);
    151     } else {
    152         return GrColor_ILLEGAL;
    153     }
    154 }
    155