1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkColorFilter.h" 9cb93a386Sopenharmony_ci#include "include/core/SkString.h" 10cb93a386Sopenharmony_ci#include "include/private/SkColorData.h" 11cb93a386Sopenharmony_ci#include "src/core/SkArenaAlloc.h" 12cb93a386Sopenharmony_ci#include "src/core/SkBlendModePriv.h" 13cb93a386Sopenharmony_ci#include "src/core/SkBlenderBase.h" 14cb93a386Sopenharmony_ci#include "src/core/SkRasterPipeline.h" 15cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h" 16cb93a386Sopenharmony_ci#include "src/core/SkRuntimeEffectPriv.h" 17cb93a386Sopenharmony_ci#include "src/core/SkVM.h" 18cb93a386Sopenharmony_ci#include "src/core/SkWriteBuffer.h" 19cb93a386Sopenharmony_ci#include "src/shaders/SkColorShader.h" 20cb93a386Sopenharmony_ci#include "src/shaders/SkComposeShader.h" 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_cinamespace { 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_cistruct LocalMatrixStageRec final : public SkStageRec { 25cb93a386Sopenharmony_ci LocalMatrixStageRec(const SkStageRec& rec, const SkMatrix& lm) 26cb93a386Sopenharmony_ci : INHERITED(rec) { 27cb93a386Sopenharmony_ci if (!lm.isIdentity()) { 28cb93a386Sopenharmony_ci if (fLocalM) { 29cb93a386Sopenharmony_ci fStorage.setConcat(lm, *fLocalM); 30cb93a386Sopenharmony_ci fLocalM = fStorage.isIdentity() ? nullptr : &fStorage; 31cb93a386Sopenharmony_ci } else { 32cb93a386Sopenharmony_ci fLocalM = &lm; 33cb93a386Sopenharmony_ci } 34cb93a386Sopenharmony_ci } 35cb93a386Sopenharmony_ci } 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ciprivate: 38cb93a386Sopenharmony_ci SkMatrix fStorage; 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ci using INHERITED = SkStageRec; 41cb93a386Sopenharmony_ci}; 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci} // namespace 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_cisk_sp<SkShader> SkShaders::Blend(SkBlendMode mode, sk_sp<SkShader> dst, sk_sp<SkShader> src) { 46cb93a386Sopenharmony_ci if (!src || !dst) { 47cb93a386Sopenharmony_ci return nullptr; 48cb93a386Sopenharmony_ci } 49cb93a386Sopenharmony_ci switch (mode) { 50cb93a386Sopenharmony_ci case SkBlendMode::kClear: return Color(0); 51cb93a386Sopenharmony_ci case SkBlendMode::kDst: return dst; 52cb93a386Sopenharmony_ci case SkBlendMode::kSrc: return src; 53cb93a386Sopenharmony_ci default: break; 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci return sk_sp<SkShader>(new SkShader_Blend(mode, std::move(dst), std::move(src))); 56cb93a386Sopenharmony_ci} 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_cisk_sp<SkShader> SkShaders::Blend(sk_sp<SkBlender> blender, sk_sp<SkShader> dst, sk_sp<SkShader> src) { 59cb93a386Sopenharmony_ci if (!src || !dst) { 60cb93a386Sopenharmony_ci return nullptr; 61cb93a386Sopenharmony_ci } 62cb93a386Sopenharmony_ci if (!blender) { 63cb93a386Sopenharmony_ci return SkShaders::Blend(SkBlendMode::kSrcOver, std::move(dst), std::move(src)); 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci if (auto bm = as_BB(blender)->asBlendMode()) { 66cb93a386Sopenharmony_ci return SkShaders::Blend(bm.value(), std::move(dst), std::move(src)); 67cb93a386Sopenharmony_ci } 68cb93a386Sopenharmony_ci return sk_sp<SkShader>(new SkShader_Blend(std::move(blender), std::move(dst), std::move(src))); 69cb93a386Sopenharmony_ci} 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_cisk_sp<SkFlattenable> SkShader_Blend::CreateProc(SkReadBuffer& buffer) { 74cb93a386Sopenharmony_ci sk_sp<SkShader> dst(buffer.readShader()); 75cb93a386Sopenharmony_ci sk_sp<SkShader> src(buffer.readShader()); 76cb93a386Sopenharmony_ci if (!buffer.validate(dst && src)) { 77cb93a386Sopenharmony_ci return nullptr; 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ci sk_sp<SkBlender> blender(nullptr); 81cb93a386Sopenharmony_ci unsigned mode = buffer.read32(); 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ci if (mode == kCustom_SkBlendMode) { 84cb93a386Sopenharmony_ci blender = buffer.readBlender(); 85cb93a386Sopenharmony_ci if (buffer.validate(blender != nullptr)) { 86cb93a386Sopenharmony_ci return SkShaders::Blend(std::move(blender), std::move(dst), std::move(src)); 87cb93a386Sopenharmony_ci } 88cb93a386Sopenharmony_ci } else { 89cb93a386Sopenharmony_ci if (buffer.validate(mode <= (unsigned)SkBlendMode::kLastMode)) { 90cb93a386Sopenharmony_ci return SkShaders::Blend(static_cast<SkBlendMode>(mode), std::move(dst), std::move(src)); 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci return nullptr; 94cb93a386Sopenharmony_ci} 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_civoid SkShader_Blend::flatten(SkWriteBuffer& buffer) const { 97cb93a386Sopenharmony_ci buffer.writeFlattenable(fDst.get()); 98cb93a386Sopenharmony_ci buffer.writeFlattenable(fSrc.get()); 99cb93a386Sopenharmony_ci if (fBlender) { 100cb93a386Sopenharmony_ci buffer.write32(kCustom_SkBlendMode); 101cb93a386Sopenharmony_ci buffer.writeFlattenable(fBlender.get()); 102cb93a386Sopenharmony_ci } else { 103cb93a386Sopenharmony_ci buffer.write32((int)fMode); 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci} 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci// Returns the output of e0, and leaves the output of e1 in r,g,b,a 108cb93a386Sopenharmony_cistatic float* append_two_shaders(const SkStageRec& rec, SkShader* s0, SkShader* s1) { 109cb93a386Sopenharmony_ci struct Storage { 110cb93a386Sopenharmony_ci float fRes0[4 * SkRasterPipeline_kMaxStride]; 111cb93a386Sopenharmony_ci }; 112cb93a386Sopenharmony_ci auto storage = rec.fAlloc->make<Storage>(); 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_ci if (!as_SB(s0)->appendStages(rec)) { 115cb93a386Sopenharmony_ci return nullptr; 116cb93a386Sopenharmony_ci } 117cb93a386Sopenharmony_ci rec.fPipeline->append(SkRasterPipeline::store_src, storage->fRes0); 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_ci if (!as_SB(s1)->appendStages(rec)) { 120cb93a386Sopenharmony_ci return nullptr; 121cb93a386Sopenharmony_ci } 122cb93a386Sopenharmony_ci return storage->fRes0; 123cb93a386Sopenharmony_ci} 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_cibool SkShader_Blend::onAppendStages(const SkStageRec& orig_rec) const { 126cb93a386Sopenharmony_ci if (fBlender) { 127cb93a386Sopenharmony_ci return false; 128cb93a386Sopenharmony_ci } 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci const LocalMatrixStageRec rec(orig_rec, this->getLocalMatrix()); 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_ci float* res0 = append_two_shaders(rec, fDst.get(), fSrc.get()); 133cb93a386Sopenharmony_ci if (!res0) { 134cb93a386Sopenharmony_ci return false; 135cb93a386Sopenharmony_ci } 136cb93a386Sopenharmony_ci 137cb93a386Sopenharmony_ci rec.fPipeline->append(SkRasterPipeline::load_dst, res0); 138cb93a386Sopenharmony_ci SkBlendMode_AppendStages(fMode, rec.fPipeline); 139cb93a386Sopenharmony_ci return true; 140cb93a386Sopenharmony_ci} 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ciskvm::Color SkShader_Blend::onProgram(skvm::Builder* p, 143cb93a386Sopenharmony_ci skvm::Coord device, skvm::Coord local, skvm::Color paint, 144cb93a386Sopenharmony_ci const SkMatrixProvider& mats, const SkMatrix* localM, 145cb93a386Sopenharmony_ci const SkColorInfo& cinfo, 146cb93a386Sopenharmony_ci skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const { 147cb93a386Sopenharmony_ci skvm::Color d,s; 148cb93a386Sopenharmony_ci if ((d = as_SB(fDst)->program(p, device,local, paint, mats,localM, cinfo, uniforms,alloc)) && 149cb93a386Sopenharmony_ci (s = as_SB(fSrc)->program(p, device,local, paint, mats,localM, cinfo, uniforms,alloc))) 150cb93a386Sopenharmony_ci { 151cb93a386Sopenharmony_ci if (fBlender) { 152cb93a386Sopenharmony_ci return as_BB(fBlender)->program(p, s,d, cinfo, uniforms,alloc); 153cb93a386Sopenharmony_ci } else { 154cb93a386Sopenharmony_ci return p->blend(fMode, s,d); 155cb93a386Sopenharmony_ci } 156cb93a386Sopenharmony_ci } 157cb93a386Sopenharmony_ci return {}; 158cb93a386Sopenharmony_ci} 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci#if SK_SUPPORT_GPU 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h" 163cb93a386Sopenharmony_ci#include "src/gpu/GrFragmentProcessor.h" 164cb93a386Sopenharmony_ci#include "src/gpu/effects/GrBlendFragmentProcessor.h" 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> SkShader_Blend::asFragmentProcessor( 167cb93a386Sopenharmony_ci const GrFPArgs& orig_args) const { 168cb93a386Sopenharmony_ci GrFPArgs::WithPreLocalMatrix args(orig_args, this->getLocalMatrix()); 169cb93a386Sopenharmony_ci auto fpA = as_SB(fDst)->asFragmentProcessor(args); 170cb93a386Sopenharmony_ci auto fpB = as_SB(fSrc)->asFragmentProcessor(args); 171cb93a386Sopenharmony_ci if (!fpA || !fpB) { 172cb93a386Sopenharmony_ci // This is unexpected. Both src and dst shaders should be valid. Just fail. 173cb93a386Sopenharmony_ci return nullptr; 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci if (fBlender) { 176cb93a386Sopenharmony_ci return as_BB(fBlender)->asFragmentProcessor(std::move(fpB), std::move(fpA), orig_args); 177cb93a386Sopenharmony_ci } else { 178cb93a386Sopenharmony_ci return GrBlendFragmentProcessor::Make(std::move(fpB), std::move(fpA), fMode); 179cb93a386Sopenharmony_ci } 180cb93a386Sopenharmony_ci} 181cb93a386Sopenharmony_ci#endif 182