Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      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 "SkBlendModePriv.h"
      9 #include "SkColorPriv.h"
     10 #include "SkMathPriv.h"
     11 #include "SkOnce.h"
     12 #include "SkOpts.h"
     13 #include "SkPM4f.h"
     14 #include "SkRasterPipeline.h"
     15 #include "SkReadBuffer.h"
     16 #include "SkString.h"
     17 #include "SkWriteBuffer.h"
     18 #include "SkXfermodePriv.h"
     19 
     20 #if SK_SUPPORT_GPU
     21 #include "GrFragmentProcessor.h"
     22 #include "effects/GrCustomXfermode.h"
     23 #include "effects/GrPorterDuffXferProcessor.h"
     24 #include "effects/GrXfermodeFragmentProcessor.h"
     25 #endif
     26 
     27 ///////////////////////////////////////////////////////////////////////////////////////////////////
     28 
     29 class SkProcCoeffXfermode : public SkXfermode {
     30 public:
     31     SkProcCoeffXfermode(SkBlendMode mode) : fMode(mode) {}
     32 
     33     void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
     34                 const SkAlpha aa[]) const override {
     35         SkASSERT(dst && src && count >= 0);
     36 
     37         SkRasterPipeline_<256> p;
     38 
     39         if (kN32_SkColorType == kBGRA_8888_SkColorType) {
     40             p.append(SkRasterPipeline::load_bgra_dst, &dst);
     41             p.append(SkRasterPipeline::load_bgra    , &src);
     42         } else {
     43             p.append(SkRasterPipeline::load_8888_dst, &dst);
     44             p.append(SkRasterPipeline::load_8888,     &src);
     45         }
     46 
     47         SkBlendMode_AppendStagesNoClamp(fMode, &p);
     48         if (aa) {
     49             p.append(SkRasterPipeline::lerp_u8, &aa);
     50         }
     51         SkBlendMode_AppendClampIfNeeded(fMode, &p);
     52 
     53         if (kN32_SkColorType == kBGRA_8888_SkColorType) {
     54             p.append(SkRasterPipeline::store_bgra, &dst);
     55         } else {
     56             p.append(SkRasterPipeline::store_8888, &dst);
     57         }
     58         p.run(0, 0, count);
     59     }
     60 
     61 private:
     62     const SkBlendMode fMode;
     63 
     64     typedef SkXfermode INHERITED;
     65 };
     66 
     67 const char* SkBlendMode_Name(SkBlendMode mode) {
     68     SkASSERT((unsigned) mode <= (unsigned)SkBlendMode::kLastMode);
     69     const char* gModeStrings[] = {
     70         "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
     71         "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
     72         "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
     73         "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
     74         "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
     75     };
     76     return gModeStrings[(int)mode];
     77     static_assert(SK_ARRAY_COUNT(gModeStrings) == (size_t)SkBlendMode::kLastMode + 1, "mode_count");
     78 }
     79 
     80 sk_sp<SkXfermode> SkXfermode::Make(SkBlendMode mode) {
     81     if ((unsigned)mode > (unsigned)SkBlendMode::kLastMode) {
     82         // report error
     83         return nullptr;
     84     }
     85 
     86     // Skia's "default" mode is srcover. nullptr in SkPaint is interpreted as srcover
     87     // so we can just return nullptr from the factory.
     88     if (SkBlendMode::kSrcOver == mode) {
     89         return nullptr;
     90     }
     91 
     92     const int COUNT_BLENDMODES = (int)SkBlendMode::kLastMode + 1;
     93 
     94     static SkOnce        once[COUNT_BLENDMODES];
     95     static SkXfermode* cached[COUNT_BLENDMODES];
     96 
     97     once[(int)mode]([mode] {
     98         if (auto xfermode = SkOpts::create_xfermode(mode)) {
     99             cached[(int)mode] = xfermode;
    100         } else {
    101             cached[(int)mode] = new SkProcCoeffXfermode(mode);
    102         }
    103     });
    104     return sk_ref_sp(cached[(int)mode]);
    105 }
    106 
    107 ///////////////////////////////////////////////////////////////////////////////////////////////////
    108 
    109 bool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) {
    110     SkBlendModeCoeff src, dst;
    111     if (!SkBlendMode_AsCoeff(mode, &src, &dst)) {
    112         return false;
    113     }
    114 
    115     switch (src) {
    116         case SkBlendModeCoeff::kDA:
    117         case SkBlendModeCoeff::kDC:
    118         case SkBlendModeCoeff::kIDA:
    119         case SkBlendModeCoeff::kIDC:
    120             return false;
    121         default:
    122             break;
    123     }
    124 
    125     switch (dst) {
    126         case SkBlendModeCoeff::kZero:
    127             return true;
    128         case SkBlendModeCoeff::kISA:
    129             return kOpaque_SrcColorOpacity == opacityType;
    130         case SkBlendModeCoeff::kSA:
    131             return kTransparentBlack_SrcColorOpacity == opacityType ||
    132             kTransparentAlpha_SrcColorOpacity == opacityType;
    133         case SkBlendModeCoeff::kSC:
    134             return kTransparentBlack_SrcColorOpacity == opacityType;
    135         default:
    136             return false;
    137     }
    138     return false;
    139 }
    140 
    141 #if SK_SUPPORT_GPU
    142 const GrXPFactory* SkBlendMode_AsXPFactory(SkBlendMode mode) {
    143     if (SkBlendMode_AsCoeff(mode, nullptr, nullptr)) {
    144         const GrXPFactory* result = GrPorterDuffXPFactory::Get(mode);
    145         SkASSERT(result);
    146         return result;
    147     }
    148 
    149     SkASSERT(GrCustomXfermode::IsSupportedMode(mode));
    150     return GrCustomXfermode::Get(mode);
    151 }
    152 #endif
    153 
    154