1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 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 "src/gpu/effects/GrBlendFragmentProcessor.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/gpu/GrFragmentProcessor.h" 11cb93a386Sopenharmony_ci#include "src/gpu/SkGr.h" 12cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLBlend.h" 13cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci// Some of the CPU implementations of blend modes differ from the GPU enough that 16cb93a386Sopenharmony_ci// we can't use the CPU implementation to implement constantOutputForConstantInput. 17cb93a386Sopenharmony_cistatic inline bool does_cpu_blend_impl_match_gpu(SkBlendMode mode) { 18cb93a386Sopenharmony_ci // The non-separable modes differ too much. So does SoftLight. ColorBurn differs too much on our 19cb93a386Sopenharmony_ci // test iOS device, but we just disable it across the board since it might differ on untested 20cb93a386Sopenharmony_ci // GPUs. 21cb93a386Sopenharmony_ci return mode <= SkBlendMode::kLastSeparableMode && mode != SkBlendMode::kSoftLight && 22cb93a386Sopenharmony_ci mode != SkBlendMode::kColorBurn; 23cb93a386Sopenharmony_ci} 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ciclass BlendFragmentProcessor : public GrFragmentProcessor { 28cb93a386Sopenharmony_cipublic: 29cb93a386Sopenharmony_ci static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> src, 30cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> dst, 31cb93a386Sopenharmony_ci SkBlendMode mode) { 32cb93a386Sopenharmony_ci return std::unique_ptr<GrFragmentProcessor>( 33cb93a386Sopenharmony_ci new BlendFragmentProcessor(std::move(src), std::move(dst), mode)); 34cb93a386Sopenharmony_ci } 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ci const char* name() const override { return "Blend"; } 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci SkString getShaderDfxInfo() const override { 39cb93a386Sopenharmony_ci SkString format; 40cb93a386Sopenharmony_ci format.printf("ShaderDfx_Blend_%d", fMode); 41cb93a386Sopenharmony_ci return format; 42cb93a386Sopenharmony_ci } 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> clone() const override; 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ciprivate: 47cb93a386Sopenharmony_ci BlendFragmentProcessor(std::unique_ptr<GrFragmentProcessor> src, 48cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> dst, 49cb93a386Sopenharmony_ci SkBlendMode mode) 50cb93a386Sopenharmony_ci : INHERITED(kBlendFragmentProcessor_ClassID, OptFlags(src.get(), dst.get(), mode)) 51cb93a386Sopenharmony_ci , fMode(mode) { 52cb93a386Sopenharmony_ci this->setIsBlendFunction(); 53cb93a386Sopenharmony_ci this->registerChild(std::move(src)); 54cb93a386Sopenharmony_ci this->registerChild(std::move(dst)); 55cb93a386Sopenharmony_ci } 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_ci BlendFragmentProcessor(const BlendFragmentProcessor& that) 58cb93a386Sopenharmony_ci : INHERITED(that) 59cb93a386Sopenharmony_ci , fMode(that.fMode) {} 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci#if GR_TEST_UTILS 62cb93a386Sopenharmony_ci SkString onDumpInfo() const override { 63cb93a386Sopenharmony_ci return SkStringPrintf("(fMode=%s)", SkBlendMode_Name(fMode)); 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci#endif 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci static OptimizationFlags OptFlags(const GrFragmentProcessor* src, 68cb93a386Sopenharmony_ci const GrFragmentProcessor* dst, SkBlendMode mode) { 69cb93a386Sopenharmony_ci OptimizationFlags flags; 70cb93a386Sopenharmony_ci switch (mode) { 71cb93a386Sopenharmony_ci case SkBlendMode::kClear: 72cb93a386Sopenharmony_ci case SkBlendMode::kSrc: 73cb93a386Sopenharmony_ci case SkBlendMode::kDst: 74cb93a386Sopenharmony_ci SkDEBUGFAIL("Shouldn't have created a Blend FP as 'clear', 'src', or 'dst'."); 75cb93a386Sopenharmony_ci flags = kNone_OptimizationFlags; 76cb93a386Sopenharmony_ci break; 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci // Produces opaque if both src and dst are opaque. These also will modulate the child's 79cb93a386Sopenharmony_ci // output by either the input color or alpha. However, if the child is not compatible 80cb93a386Sopenharmony_ci // with the coverage as alpha then it may produce a color that is not valid premul. 81cb93a386Sopenharmony_ci case SkBlendMode::kSrcIn: 82cb93a386Sopenharmony_ci case SkBlendMode::kDstIn: 83cb93a386Sopenharmony_ci case SkBlendMode::kModulate: 84cb93a386Sopenharmony_ci if (src && dst) { 85cb93a386Sopenharmony_ci flags = ProcessorOptimizationFlags(src) & ProcessorOptimizationFlags(dst) & 86cb93a386Sopenharmony_ci kPreservesOpaqueInput_OptimizationFlag; 87cb93a386Sopenharmony_ci } else if (src) { 88cb93a386Sopenharmony_ci flags = ProcessorOptimizationFlags(src) & 89cb93a386Sopenharmony_ci ~kConstantOutputForConstantInput_OptimizationFlag; 90cb93a386Sopenharmony_ci } else if (dst) { 91cb93a386Sopenharmony_ci flags = ProcessorOptimizationFlags(dst) & 92cb93a386Sopenharmony_ci ~kConstantOutputForConstantInput_OptimizationFlag; 93cb93a386Sopenharmony_ci } else { 94cb93a386Sopenharmony_ci flags = kNone_OptimizationFlags; 95cb93a386Sopenharmony_ci } 96cb93a386Sopenharmony_ci break; 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci // Produces zero when both are opaque, indeterminate if one is opaque. 99cb93a386Sopenharmony_ci case SkBlendMode::kSrcOut: 100cb93a386Sopenharmony_ci case SkBlendMode::kDstOut: 101cb93a386Sopenharmony_ci case SkBlendMode::kXor: 102cb93a386Sopenharmony_ci flags = kNone_OptimizationFlags; 103cb93a386Sopenharmony_ci break; 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci // Is opaque if the dst is opaque. 106cb93a386Sopenharmony_ci case SkBlendMode::kSrcATop: 107cb93a386Sopenharmony_ci flags = ProcessorOptimizationFlags(dst) & kPreservesOpaqueInput_OptimizationFlag; 108cb93a386Sopenharmony_ci break; 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque. 111cb93a386Sopenharmony_ci case SkBlendMode::kDstATop: 112cb93a386Sopenharmony_ci case SkBlendMode::kScreen: 113cb93a386Sopenharmony_ci flags = ProcessorOptimizationFlags(src) & kPreservesOpaqueInput_OptimizationFlag; 114cb93a386Sopenharmony_ci break; 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci // These modes are all opaque if either src or dst is opaque. All the advanced modes 117cb93a386Sopenharmony_ci // compute alpha as src-over. 118cb93a386Sopenharmony_ci case SkBlendMode::kSrcOver: 119cb93a386Sopenharmony_ci case SkBlendMode::kDstOver: 120cb93a386Sopenharmony_ci case SkBlendMode::kPlus: 121cb93a386Sopenharmony_ci case SkBlendMode::kOverlay: 122cb93a386Sopenharmony_ci case SkBlendMode::kDarken: 123cb93a386Sopenharmony_ci case SkBlendMode::kLighten: 124cb93a386Sopenharmony_ci case SkBlendMode::kColorDodge: 125cb93a386Sopenharmony_ci case SkBlendMode::kColorBurn: 126cb93a386Sopenharmony_ci case SkBlendMode::kHardLight: 127cb93a386Sopenharmony_ci case SkBlendMode::kSoftLight: 128cb93a386Sopenharmony_ci case SkBlendMode::kDifference: 129cb93a386Sopenharmony_ci case SkBlendMode::kExclusion: 130cb93a386Sopenharmony_ci case SkBlendMode::kMultiply: 131cb93a386Sopenharmony_ci case SkBlendMode::kHue: 132cb93a386Sopenharmony_ci case SkBlendMode::kSaturation: 133cb93a386Sopenharmony_ci case SkBlendMode::kColor: 134cb93a386Sopenharmony_ci case SkBlendMode::kLuminosity: 135cb93a386Sopenharmony_ci flags = (ProcessorOptimizationFlags(src) | ProcessorOptimizationFlags(dst)) & 136cb93a386Sopenharmony_ci kPreservesOpaqueInput_OptimizationFlag; 137cb93a386Sopenharmony_ci break; 138cb93a386Sopenharmony_ci } 139cb93a386Sopenharmony_ci if (does_cpu_blend_impl_match_gpu(mode) && 140cb93a386Sopenharmony_ci (!src || src->hasConstantOutputForConstantInput()) && 141cb93a386Sopenharmony_ci (!dst || dst->hasConstantOutputForConstantInput())) { 142cb93a386Sopenharmony_ci flags |= kConstantOutputForConstantInput_OptimizationFlag; 143cb93a386Sopenharmony_ci } 144cb93a386Sopenharmony_ci return flags; 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override { 148cb93a386Sopenharmony_ci b->add32((int)fMode); 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci bool onIsEqual(const GrFragmentProcessor& other) const override { 152cb93a386Sopenharmony_ci const BlendFragmentProcessor& cs = other.cast<BlendFragmentProcessor>(); 153cb93a386Sopenharmony_ci return fMode == cs.fMode; 154cb93a386Sopenharmony_ci } 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_ci SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override { 157cb93a386Sopenharmony_ci const auto* src = this->childProcessor(0); 158cb93a386Sopenharmony_ci const auto* dst = this->childProcessor(1); 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci SkPMColor4f srcColor = ConstantOutputForConstantInput(src, input); 161cb93a386Sopenharmony_ci SkPMColor4f dstColor = ConstantOutputForConstantInput(dst, input); 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ci return SkBlendMode_Apply(fMode, srcColor, dstColor); 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override; 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci SkBlendMode fMode; 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci GR_DECLARE_FRAGMENT_PROCESSOR_TEST 171cb93a386Sopenharmony_ci 172cb93a386Sopenharmony_ci using INHERITED = GrFragmentProcessor; 173cb93a386Sopenharmony_ci}; 174cb93a386Sopenharmony_ci 175cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////// 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_ciGR_DEFINE_FRAGMENT_PROCESSOR_TEST(BlendFragmentProcessor); 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ci#if GR_TEST_UTILS 181cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> BlendFragmentProcessor::TestCreate(GrProcessorTestData* d) { 182cb93a386Sopenharmony_ci // Create one or two random fragment processors. 183cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> src(GrProcessorUnitTest::MakeOptionalChildFP(d)); 184cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d)); 185cb93a386Sopenharmony_ci if (d->fRandom->nextBool()) { 186cb93a386Sopenharmony_ci std::swap(src, dst); 187cb93a386Sopenharmony_ci } 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci SkBlendMode mode; 190cb93a386Sopenharmony_ci do { 191cb93a386Sopenharmony_ci mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode)); 192cb93a386Sopenharmony_ci } while (SkBlendMode::kClear == mode || SkBlendMode::kSrc == mode || SkBlendMode::kDst == mode); 193cb93a386Sopenharmony_ci return std::unique_ptr<GrFragmentProcessor>( 194cb93a386Sopenharmony_ci new BlendFragmentProcessor(std::move(src), std::move(dst), mode)); 195cb93a386Sopenharmony_ci} 196cb93a386Sopenharmony_ci#endif 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> BlendFragmentProcessor::clone() const { 199cb93a386Sopenharmony_ci return std::unique_ptr<GrFragmentProcessor>(new BlendFragmentProcessor(*this)); 200cb93a386Sopenharmony_ci} 201cb93a386Sopenharmony_ci 202cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor::ProgramImpl> BlendFragmentProcessor::onMakeProgramImpl() const { 203cb93a386Sopenharmony_ci class Impl : public ProgramImpl { 204cb93a386Sopenharmony_ci public: 205cb93a386Sopenharmony_ci void emitCode(EmitArgs& args) override { 206cb93a386Sopenharmony_ci GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 207cb93a386Sopenharmony_ci const BlendFragmentProcessor& bfp = args.fFp.cast<BlendFragmentProcessor>(); 208cb93a386Sopenharmony_ci SkBlendMode mode = bfp.fMode; 209cb93a386Sopenharmony_ci 210cb93a386Sopenharmony_ci fragBuilder->codeAppendf("// Blend mode: %s\n", SkBlendMode_Name(mode)); 211cb93a386Sopenharmony_ci 212cb93a386Sopenharmony_ci // Invoke src/dst with our input color (or substitute input color if no child FP) 213cb93a386Sopenharmony_ci SkString srcColor = this->invokeChild(0, args); 214cb93a386Sopenharmony_ci SkString dstColor = this->invokeChild(1, args); 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_ci // Blend src and dst colors together. 217cb93a386Sopenharmony_ci fragBuilder->codeAppendf("return %s(%s, %s);", 218cb93a386Sopenharmony_ci GrGLSLBlend::BlendFuncName(mode), 219cb93a386Sopenharmony_ci srcColor.c_str(), 220cb93a386Sopenharmony_ci dstColor.c_str()); 221cb93a386Sopenharmony_ci } 222cb93a386Sopenharmony_ci }; 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ci return std::make_unique<Impl>(); 225cb93a386Sopenharmony_ci} 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> GrBlendFragmentProcessor::Make( 230cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> src, 231cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> dst, 232cb93a386Sopenharmony_ci SkBlendMode mode) { 233cb93a386Sopenharmony_ci switch (mode) { 234cb93a386Sopenharmony_ci case SkBlendMode::kClear: 235cb93a386Sopenharmony_ci return GrFragmentProcessor::MakeColor(SK_PMColor4fTRANSPARENT); 236cb93a386Sopenharmony_ci case SkBlendMode::kSrc: 237cb93a386Sopenharmony_ci return src; 238cb93a386Sopenharmony_ci case SkBlendMode::kDst: 239cb93a386Sopenharmony_ci return dst; 240cb93a386Sopenharmony_ci default: 241cb93a386Sopenharmony_ci return BlendFragmentProcessor::Make(std::move(src), std::move(dst), mode); 242cb93a386Sopenharmony_ci } 243cb93a386Sopenharmony_ci} 244