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