SkBlendMode.cpp revision fb126fa96e0f49f5dc17a9a043acced68be99e93
1/* 2 * Copyright 2017 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 "SkBlendModePriv.h" 9#include "SkRasterPipeline.h" 10#include "../jumper/SkJumper.h" 11 12bool SkBlendMode_SupportsCoverageAsAlpha(SkBlendMode mode) { 13 switch (mode) { 14 case SkBlendMode::kDst: 15 case SkBlendMode::kSrcOver: 16 case SkBlendMode::kDstOver: 17 case SkBlendMode::kDstOut: 18 case SkBlendMode::kSrcATop: 19 case SkBlendMode::kXor: 20 case SkBlendMode::kPlus: 21 return true; 22 default: 23 break; 24 } 25 return false; 26} 27 28struct CoeffRec { 29 SkBlendModeCoeff fSrc; 30 SkBlendModeCoeff fDst; 31}; 32 33const CoeffRec gCoeffs[] = { 34 { SkBlendModeCoeff::kZero, SkBlendModeCoeff::kZero }, 35 { SkBlendModeCoeff::kOne, SkBlendModeCoeff::kZero }, 36 { SkBlendModeCoeff::kZero, SkBlendModeCoeff::kOne }, 37 { SkBlendModeCoeff::kOne, SkBlendModeCoeff::kISA }, 38 { SkBlendModeCoeff::kIDA, SkBlendModeCoeff::kOne }, 39 { SkBlendModeCoeff::kDA, SkBlendModeCoeff::kZero }, 40 { SkBlendModeCoeff::kZero, SkBlendModeCoeff::kSA }, 41 { SkBlendModeCoeff::kIDA, SkBlendModeCoeff::kZero }, 42 { SkBlendModeCoeff::kZero, SkBlendModeCoeff::kISA }, 43 { SkBlendModeCoeff::kDA, SkBlendModeCoeff::kISA }, 44 { SkBlendModeCoeff::kIDA, SkBlendModeCoeff::kSA }, 45 { SkBlendModeCoeff::kIDA, SkBlendModeCoeff::kISA }, 46 47 { SkBlendModeCoeff::kOne, SkBlendModeCoeff::kOne }, 48 { SkBlendModeCoeff::kZero, SkBlendModeCoeff::kSC }, 49 { SkBlendModeCoeff::kOne, SkBlendModeCoeff::kISC }, // screen 50}; 51 52bool SkBlendMode_AsCoeff(SkBlendMode mode, SkBlendModeCoeff* src, SkBlendModeCoeff* dst) { 53 if (mode > SkBlendMode::kScreen) { 54 return false; 55 } 56 if (src) { 57 *src = gCoeffs[static_cast<int>(mode)].fSrc; 58 } 59 if (dst) { 60 *dst = gCoeffs[static_cast<int>(mode)].fDst; 61 } 62 return true; 63} 64 65bool SkBlendMode_ShouldPreScaleCoverage(SkBlendMode mode, bool rgb_coverage) { 66 // The most important things we do here are: 67 // - always use pre-scaling for plus mode; 68 // - never use pre-scaling for srcover with 565 coverage. 69 return mode == SkBlendMode::kPlus || 70 (mode == SkBlendMode::kSrcOver && !rgb_coverage); 71} 72 73void SkBlendMode_AppendStages(SkBlendMode mode, SkRasterPipeline* p) { 74 auto stage = SkRasterPipeline::srcover; 75 switch (mode) { 76 case SkBlendMode::kClear: stage = SkRasterPipeline::clear; break; 77 case SkBlendMode::kSrc: return; // This stage is a no-op. 78 case SkBlendMode::kDst: stage = SkRasterPipeline::move_dst_src; break; 79 case SkBlendMode::kSrcOver: stage = SkRasterPipeline::srcover; break; 80 case SkBlendMode::kDstOver: stage = SkRasterPipeline::dstover; break; 81 case SkBlendMode::kSrcIn: stage = SkRasterPipeline::srcin; break; 82 case SkBlendMode::kDstIn: stage = SkRasterPipeline::dstin; break; 83 case SkBlendMode::kSrcOut: stage = SkRasterPipeline::srcout; break; 84 case SkBlendMode::kDstOut: stage = SkRasterPipeline::dstout; break; 85 case SkBlendMode::kSrcATop: stage = SkRasterPipeline::srcatop; break; 86 case SkBlendMode::kDstATop: stage = SkRasterPipeline::dstatop; break; 87 case SkBlendMode::kXor: stage = SkRasterPipeline::xor_; break; 88 case SkBlendMode::kPlus: stage = SkRasterPipeline::plus_; break; 89 case SkBlendMode::kModulate: stage = SkRasterPipeline::modulate; break; 90 91 case SkBlendMode::kScreen: stage = SkRasterPipeline::screen; break; 92 case SkBlendMode::kOverlay: stage = SkRasterPipeline::overlay; break; 93 case SkBlendMode::kDarken: stage = SkRasterPipeline::darken; break; 94 case SkBlendMode::kLighten: stage = SkRasterPipeline::lighten; break; 95 case SkBlendMode::kColorDodge: stage = SkRasterPipeline::colordodge; break; 96 case SkBlendMode::kColorBurn: stage = SkRasterPipeline::colorburn; break; 97 case SkBlendMode::kHardLight: stage = SkRasterPipeline::hardlight; break; 98 case SkBlendMode::kSoftLight: stage = SkRasterPipeline::softlight; break; 99 case SkBlendMode::kDifference: stage = SkRasterPipeline::difference; break; 100 case SkBlendMode::kExclusion: stage = SkRasterPipeline::exclusion; break; 101 case SkBlendMode::kMultiply: stage = SkRasterPipeline::multiply; break; 102 103 case SkBlendMode::kHue: stage = SkRasterPipeline::hue; break; 104 case SkBlendMode::kSaturation: stage = SkRasterPipeline::saturation; break; 105 case SkBlendMode::kColor: stage = SkRasterPipeline::color; break; 106 case SkBlendMode::kLuminosity: stage = SkRasterPipeline::luminosity; break; 107 } 108 p->append(stage); 109} 110 111SkPM4f SkBlendMode_Apply(SkBlendMode mode, const SkPM4f& src, const SkPM4f& dst) { 112 // special-case simple/common modes... 113 switch (mode) { 114 case SkBlendMode::kClear: return {{ 0, 0, 0, 0 }}; 115 case SkBlendMode::kSrc: return src; 116 case SkBlendMode::kDst: return dst; 117 case SkBlendMode::kSrcOver: 118 return SkPM4f::From4f(src.to4f() + dst.to4f() * Sk4f(1 - src.a())); 119 default: 120 break; 121 } 122 123 SkRasterPipeline_<256> p; 124 SkPM4f src_storage = src, 125 dst_storage = dst, 126 res_storage; 127 SkJumper_MemoryCtx src_ctx = { &src_storage, 0 }, 128 dst_ctx = { &dst_storage, 0 }, 129 res_ctx = { &res_storage, 0 }; 130 131 p.append(SkRasterPipeline::load_f32, &dst_ctx); 132 p.append(SkRasterPipeline::move_src_dst); 133 p.append(SkRasterPipeline::load_f32, &src_ctx); 134 SkBlendMode_AppendStages(mode, &p); 135 p.append(SkRasterPipeline::store_f32, &res_ctx); 136 p.run(0,0, 1,1); 137 return res_storage; 138} 139