1/* 2 * Copyright 2021 Google LLC 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 "src/core/SkBlendModeBlender.h" 9#include "src/core/SkReadBuffer.h" 10#include "src/core/SkWriteBuffer.h" 11 12#if SK_SUPPORT_GPU 13#include "src/gpu/GrFragmentProcessor.h" 14#include "src/gpu/effects/GrBlendFragmentProcessor.h" 15#endif 16 17sk_sp<SkBlender> SkBlender::Mode(SkBlendMode mode) { 18#define RETURN_SINGLETON_BLENDER(m) \ 19 case m: { \ 20 static auto* sBlender = new SkBlendModeBlender{m}; \ 21 return sk_ref_sp(sBlender); \ 22 } 23 24 switch (mode) { 25 RETURN_SINGLETON_BLENDER(SkBlendMode::kClear) 26 RETURN_SINGLETON_BLENDER(SkBlendMode::kSrc) 27 RETURN_SINGLETON_BLENDER(SkBlendMode::kDst) 28 RETURN_SINGLETON_BLENDER(SkBlendMode::kSrcOver) 29 RETURN_SINGLETON_BLENDER(SkBlendMode::kDstOver) 30 RETURN_SINGLETON_BLENDER(SkBlendMode::kSrcIn) 31 RETURN_SINGLETON_BLENDER(SkBlendMode::kDstIn) 32 RETURN_SINGLETON_BLENDER(SkBlendMode::kSrcOut) 33 RETURN_SINGLETON_BLENDER(SkBlendMode::kDstOut) 34 RETURN_SINGLETON_BLENDER(SkBlendMode::kSrcATop) 35 RETURN_SINGLETON_BLENDER(SkBlendMode::kDstATop) 36 RETURN_SINGLETON_BLENDER(SkBlendMode::kXor) 37 RETURN_SINGLETON_BLENDER(SkBlendMode::kPlus) 38 RETURN_SINGLETON_BLENDER(SkBlendMode::kModulate) 39 RETURN_SINGLETON_BLENDER(SkBlendMode::kScreen) 40 RETURN_SINGLETON_BLENDER(SkBlendMode::kOverlay) 41 RETURN_SINGLETON_BLENDER(SkBlendMode::kDarken) 42 RETURN_SINGLETON_BLENDER(SkBlendMode::kLighten) 43 RETURN_SINGLETON_BLENDER(SkBlendMode::kColorDodge) 44 RETURN_SINGLETON_BLENDER(SkBlendMode::kColorBurn) 45 RETURN_SINGLETON_BLENDER(SkBlendMode::kHardLight) 46 RETURN_SINGLETON_BLENDER(SkBlendMode::kSoftLight) 47 RETURN_SINGLETON_BLENDER(SkBlendMode::kDifference) 48 RETURN_SINGLETON_BLENDER(SkBlendMode::kExclusion) 49 RETURN_SINGLETON_BLENDER(SkBlendMode::kMultiply) 50 RETURN_SINGLETON_BLENDER(SkBlendMode::kHue) 51 RETURN_SINGLETON_BLENDER(SkBlendMode::kSaturation) 52 RETURN_SINGLETON_BLENDER(SkBlendMode::kColor) 53 RETURN_SINGLETON_BLENDER(SkBlendMode::kLuminosity) 54 } 55 56 SkDEBUGFAILF("invalid blend mode %d", (int)mode); 57 return nullptr; 58 59#undef RETURN_SINGLETON_BLENDER 60} 61 62sk_sp<SkFlattenable> SkBlendModeBlender::CreateProc(SkReadBuffer& buffer) { 63 SkBlendMode mode = buffer.read32LE(SkBlendMode::kLastMode); 64 return SkBlender::Mode(mode); 65} 66 67void SkBlendModeBlender::flatten(SkWriteBuffer& buffer) const { 68 buffer.writeInt((int)fMode); 69} 70 71#if SK_SUPPORT_GPU 72std::unique_ptr<GrFragmentProcessor> SkBlendModeBlender::asFragmentProcessor( 73 std::unique_ptr<GrFragmentProcessor> srcFP, 74 std::unique_ptr<GrFragmentProcessor> dstFP, 75 const GrFPArgs& fpArgs) const { 76 // Note that for the final blend onto the canvas, we should prefer to use the GrXferProcessor 77 // instead of a SkBlendModeBlender to perform the blend. The Xfer processor is able to perform 78 // coefficient-based blends directly, without readback. This will be much more efficient. 79 return GrBlendFragmentProcessor::Make( 80 std::move(srcFP), GrFragmentProcessor::UseDestColorAsInput(std::move(dstFP)), fMode); 81} 82#endif 83 84skvm::Color SkBlendModeBlender::onProgram(skvm::Builder* p, skvm::Color src, skvm::Color dst, 85 const SkColorInfo& colorInfo, skvm::Uniforms* uniforms, 86 SkArenaAlloc* alloc) const { 87 return p->blend(fMode, src, dst); 88} 89