1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 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/GrSkSLFP.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/effects/SkRuntimeEffect.h" 11cb93a386Sopenharmony_ci#include "include/private/GrContext_Base.h" 12cb93a386Sopenharmony_ci#include "include/private/SkSLString.h" 13cb93a386Sopenharmony_ci#include "src/core/SkRuntimeEffectPriv.h" 14cb93a386Sopenharmony_ci#include "src/core/SkVM.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrBaseContextPriv.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrColorInfo.h" 17cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h" 18cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" 19cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLProgramBuilder.h" 20cb93a386Sopenharmony_ci#include "src/sksl/SkSLUtil.h" 21cb93a386Sopenharmony_ci#include "src/sksl/codegen/SkSLPipelineStageCodeGenerator.h" 22cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLVarDeclarations.h" 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ciclass GrSkSLFP::Impl : public ProgramImpl { 25cb93a386Sopenharmony_cipublic: 26cb93a386Sopenharmony_ci void emitCode(EmitArgs& args) override { 27cb93a386Sopenharmony_ci const GrSkSLFP& fp = args.fFp.cast<GrSkSLFP>(); 28cb93a386Sopenharmony_ci const SkSL::Program& program = *fp.fEffect->fBaseProgram; 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci class FPCallbacks : public SkSL::PipelineStage::Callbacks { 31cb93a386Sopenharmony_ci public: 32cb93a386Sopenharmony_ci FPCallbacks(Impl* self, 33cb93a386Sopenharmony_ci EmitArgs& args, 34cb93a386Sopenharmony_ci const char* inputColor, 35cb93a386Sopenharmony_ci const SkSL::Context& context, 36cb93a386Sopenharmony_ci const uint8_t* uniformData, 37cb93a386Sopenharmony_ci const GrSkSLFP::UniformFlags* uniformFlags) 38cb93a386Sopenharmony_ci : fSelf(self) 39cb93a386Sopenharmony_ci , fArgs(args) 40cb93a386Sopenharmony_ci , fInputColor(inputColor) 41cb93a386Sopenharmony_ci , fContext(context) 42cb93a386Sopenharmony_ci , fUniformData(uniformData) 43cb93a386Sopenharmony_ci , fUniformFlags(uniformFlags) {} 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ci using String = SkSL::String; 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ci String declareUniform(const SkSL::VarDeclaration* decl) override { 48cb93a386Sopenharmony_ci const SkSL::Variable& var = decl->var(); 49cb93a386Sopenharmony_ci if (var.type().isOpaque()) { 50cb93a386Sopenharmony_ci // Nothing to do. The only opaque types we should see are children, and those 51cb93a386Sopenharmony_ci // are handled specially, above. 52cb93a386Sopenharmony_ci SkASSERT(var.type().isEffectChild()); 53cb93a386Sopenharmony_ci return String(var.name()); 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci const SkSL::Type* type = &var.type(); 57cb93a386Sopenharmony_ci size_t sizeInBytes = type->slotCount() * sizeof(float); 58cb93a386Sopenharmony_ci const float* floatData = reinterpret_cast<const float*>(fUniformData); 59cb93a386Sopenharmony_ci const int* intData = reinterpret_cast<const int*>(fUniformData); 60cb93a386Sopenharmony_ci fUniformData += sizeInBytes; 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ci bool isArray = false; 63cb93a386Sopenharmony_ci if (type->isArray()) { 64cb93a386Sopenharmony_ci type = &type->componentType(); 65cb93a386Sopenharmony_ci isArray = true; 66cb93a386Sopenharmony_ci } 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci GrSLType gpuType; 69cb93a386Sopenharmony_ci SkAssertResult(SkSL::type_to_grsltype(fContext, *type, &gpuType)); 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci if (*fUniformFlags++ & GrSkSLFP::kSpecialize_Flag) { 72cb93a386Sopenharmony_ci SkASSERTF(!isArray, "specializing array uniforms is not allowed"); 73cb93a386Sopenharmony_ci String value = GrGLSLTypeString(gpuType); 74cb93a386Sopenharmony_ci value.append("("); 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci bool isFloat = GrSLTypeIsFloatType(gpuType); 77cb93a386Sopenharmony_ci size_t slots = type->slotCount(); 78cb93a386Sopenharmony_ci for (size_t i = 0; i < slots; ++i) { 79cb93a386Sopenharmony_ci value.append(isFloat ? SkSL::to_string(floatData[i]) 80cb93a386Sopenharmony_ci : SkSL::to_string(intData[i])); 81cb93a386Sopenharmony_ci value.append(","); 82cb93a386Sopenharmony_ci } 83cb93a386Sopenharmony_ci value.back() = ')'; 84cb93a386Sopenharmony_ci return value; 85cb93a386Sopenharmony_ci } 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ci const char* uniformName = nullptr; 88cb93a386Sopenharmony_ci auto handle = 89cb93a386Sopenharmony_ci fArgs.fUniformHandler->addUniformArray(&fArgs.fFp.cast<GrSkSLFP>(), 90cb93a386Sopenharmony_ci kFragment_GrShaderFlag, 91cb93a386Sopenharmony_ci gpuType, 92cb93a386Sopenharmony_ci SkString(var.name()).c_str(), 93cb93a386Sopenharmony_ci isArray ? var.type().columns() : 0, 94cb93a386Sopenharmony_ci &uniformName); 95cb93a386Sopenharmony_ci fSelf->fUniformHandles.push_back(handle); 96cb93a386Sopenharmony_ci return String(uniformName); 97cb93a386Sopenharmony_ci } 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci String getMangledName(const char* name) override { 100cb93a386Sopenharmony_ci return String(fArgs.fFragBuilder->getMangledFunctionName(name).c_str()); 101cb93a386Sopenharmony_ci } 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci void defineFunction(const char* decl, const char* body, bool isMain) override { 104cb93a386Sopenharmony_ci if (isMain) { 105cb93a386Sopenharmony_ci fArgs.fFragBuilder->codeAppend(body); 106cb93a386Sopenharmony_ci } else { 107cb93a386Sopenharmony_ci fArgs.fFragBuilder->emitFunction(decl, body); 108cb93a386Sopenharmony_ci } 109cb93a386Sopenharmony_ci } 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ci void declareFunction(const char* decl) override { 112cb93a386Sopenharmony_ci fArgs.fFragBuilder->emitFunctionPrototype(decl); 113cb93a386Sopenharmony_ci } 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci void defineStruct(const char* definition) override { 116cb93a386Sopenharmony_ci fArgs.fFragBuilder->definitionAppend(definition); 117cb93a386Sopenharmony_ci } 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_ci void declareGlobal(const char* declaration) override { 120cb93a386Sopenharmony_ci fArgs.fFragBuilder->definitionAppend(declaration); 121cb93a386Sopenharmony_ci } 122cb93a386Sopenharmony_ci 123cb93a386Sopenharmony_ci String sampleShader(int index, String coords) override { 124cb93a386Sopenharmony_ci // If the child was sampled using the coords passed to main (and they are never 125cb93a386Sopenharmony_ci // modified), then we will have marked the child as PassThrough. The code generator 126cb93a386Sopenharmony_ci // doesn't know that, and still supplies coords. Inside invokeChild, we assert that 127cb93a386Sopenharmony_ci // any coords passed for a PassThrough child match args.fSampleCoords exactly. 128cb93a386Sopenharmony_ci // 129cb93a386Sopenharmony_ci // Normally, this is valid. Here, we *copied* the sample coords to a local variable 130cb93a386Sopenharmony_ci // (so that they're mutable in the runtime effect SkSL). Thus, the coords string we 131cb93a386Sopenharmony_ci // get here is the name of the local copy, and fSampleCoords still points to the 132cb93a386Sopenharmony_ci // unmodified original (which might be a varying, for example). 133cb93a386Sopenharmony_ci // To prevent the assert, we pass the empty string in this case. Note that for 134cb93a386Sopenharmony_ci // children sampled like this, invokeChild doesn't even use the coords parameter, 135cb93a386Sopenharmony_ci // except for that assert. 136cb93a386Sopenharmony_ci const GrFragmentProcessor* child = fArgs.fFp.childProcessor(index); 137cb93a386Sopenharmony_ci if (child && child->sampleUsage().isPassThrough()) { 138cb93a386Sopenharmony_ci coords.clear(); 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci return String(fSelf->invokeChild(index, fInputColor, fArgs, coords).c_str()); 141cb93a386Sopenharmony_ci } 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci String sampleColorFilter(int index, String color) override { 144cb93a386Sopenharmony_ci return String(fSelf->invokeChild(index, 145cb93a386Sopenharmony_ci color.empty() ? fInputColor : color.c_str(), 146cb93a386Sopenharmony_ci fArgs) 147cb93a386Sopenharmony_ci .c_str()); 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci 150cb93a386Sopenharmony_ci String sampleBlender(int index, String src, String dst) override { 151cb93a386Sopenharmony_ci if (!fSelf->childProcessor(index)) { 152cb93a386Sopenharmony_ci return String::printf("blend_src_over(%s, %s)", src.c_str(), dst.c_str()); 153cb93a386Sopenharmony_ci } 154cb93a386Sopenharmony_ci return String(fSelf->invokeChild(index, src.c_str(), dst.c_str(), fArgs).c_str()); 155cb93a386Sopenharmony_ci } 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci Impl* fSelf; 158cb93a386Sopenharmony_ci EmitArgs& fArgs; 159cb93a386Sopenharmony_ci const char* fInputColor; 160cb93a386Sopenharmony_ci const SkSL::Context& fContext; 161cb93a386Sopenharmony_ci const uint8_t* fUniformData; 162cb93a386Sopenharmony_ci const GrSkSLFP::UniformFlags* fUniformFlags; 163cb93a386Sopenharmony_ci int fUniformIndex = 0; 164cb93a386Sopenharmony_ci }; 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci // If we have an input child, we invoke it now, and make the result of that be the "input 167cb93a386Sopenharmony_ci // color" for all other purposes later (eg, the default passed via sample calls, etc.) 168cb93a386Sopenharmony_ci if (fp.fInputChildIndex >= 0) { 169cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf("%s = %s;\n", 170cb93a386Sopenharmony_ci args.fInputColor, 171cb93a386Sopenharmony_ci this->invokeChild(fp.fInputChildIndex, args).c_str()); 172cb93a386Sopenharmony_ci } 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci if (fp.fEffect->allowBlender()) { 175cb93a386Sopenharmony_ci // If we have an dest-color child, we invoke it now, and make the result of that be the 176cb93a386Sopenharmony_ci // "dest color" for all other purposes later. 177cb93a386Sopenharmony_ci if (fp.fDestColorChildIndex >= 0) { 178cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf( 179cb93a386Sopenharmony_ci "%s = %s;\n", 180cb93a386Sopenharmony_ci args.fDestColor, 181cb93a386Sopenharmony_ci this->invokeChild(fp.fDestColorChildIndex, args.fDestColor, args).c_str()); 182cb93a386Sopenharmony_ci } 183cb93a386Sopenharmony_ci } else { 184cb93a386Sopenharmony_ci // We're not making a blender, so we don't expect a dest-color child FP to exist. 185cb93a386Sopenharmony_ci SkASSERT(fp.fDestColorChildIndex < 0); 186cb93a386Sopenharmony_ci } 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_ci // Snap off a global copy of the input color at the start of main. We need this when 189cb93a386Sopenharmony_ci // we call child processors (particularly from helper functions, which can't "see" the 190cb93a386Sopenharmony_ci // parameter to main). Even from within main, if the code mutates the parameter, calls to 191cb93a386Sopenharmony_ci // sample should still be passing the original color (by default). 192cb93a386Sopenharmony_ci SkString inputColorName; 193cb93a386Sopenharmony_ci if (fp.fEffect->samplesOutsideMain()) { 194cb93a386Sopenharmony_ci GrShaderVar inputColorCopy(args.fFragBuilder->getMangledFunctionName("inColor"), 195cb93a386Sopenharmony_ci kHalf4_GrSLType); 196cb93a386Sopenharmony_ci args.fFragBuilder->declareGlobal(inputColorCopy); 197cb93a386Sopenharmony_ci inputColorName = inputColorCopy.getName(); 198cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf("%s = %s;\n", inputColorName.c_str(), args.fInputColor); 199cb93a386Sopenharmony_ci } else { 200cb93a386Sopenharmony_ci inputColorName = args.fFragBuilder->newTmpVarName("inColor"); 201cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf( 202cb93a386Sopenharmony_ci "half4 %s = %s;\n", inputColorName.c_str(), args.fInputColor); 203cb93a386Sopenharmony_ci } 204cb93a386Sopenharmony_ci 205cb93a386Sopenharmony_ci // Copy the incoming coords to a local variable. Code in main might modify the coords 206cb93a386Sopenharmony_ci // parameter. fSampleCoord could be a varying, so writes to it would be illegal. 207cb93a386Sopenharmony_ci const char* coords = "float2(0)"; 208cb93a386Sopenharmony_ci SkString coordsVarName; 209cb93a386Sopenharmony_ci if (fp.usesSampleCoordsDirectly()) { 210cb93a386Sopenharmony_ci coordsVarName = args.fFragBuilder->newTmpVarName("coords"); 211cb93a386Sopenharmony_ci coords = coordsVarName.c_str(); 212cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf("float2 %s = %s;\n", coords, args.fSampleCoord); 213cb93a386Sopenharmony_ci } 214cb93a386Sopenharmony_ci 215cb93a386Sopenharmony_ci FPCallbacks callbacks(this, 216cb93a386Sopenharmony_ci args, 217cb93a386Sopenharmony_ci inputColorName.c_str(), 218cb93a386Sopenharmony_ci *program.fContext, 219cb93a386Sopenharmony_ci fp.uniformData(), 220cb93a386Sopenharmony_ci fp.uniformFlags()); 221cb93a386Sopenharmony_ci SkSL::PipelineStage::ConvertProgram( 222cb93a386Sopenharmony_ci program, coords, args.fInputColor, args.fDestColor, &callbacks); 223cb93a386Sopenharmony_ci } 224cb93a386Sopenharmony_ci 225cb93a386Sopenharmony_ciprivate: 226cb93a386Sopenharmony_ci void onSetData(const GrGLSLProgramDataManager& pdman, 227cb93a386Sopenharmony_ci const GrFragmentProcessor& _proc) override { 228cb93a386Sopenharmony_ci using Type = SkRuntimeEffect::Uniform::Type; 229cb93a386Sopenharmony_ci size_t uniIndex = 0; 230cb93a386Sopenharmony_ci const GrSkSLFP& outer = _proc.cast<GrSkSLFP>(); 231cb93a386Sopenharmony_ci const uint8_t* uniformData = outer.uniformData(); 232cb93a386Sopenharmony_ci const GrSkSLFP::UniformFlags* uniformFlags = outer.uniformFlags(); 233cb93a386Sopenharmony_ci for (const auto& v : outer.fEffect->uniforms()) { 234cb93a386Sopenharmony_ci if (*uniformFlags++ & GrSkSLFP::kSpecialize_Flag) { 235cb93a386Sopenharmony_ci continue; 236cb93a386Sopenharmony_ci } 237cb93a386Sopenharmony_ci const UniformHandle handle = fUniformHandles[uniIndex++]; 238cb93a386Sopenharmony_ci auto floatData = [=] { return SkTAddOffset<const float>(uniformData, v.offset); }; 239cb93a386Sopenharmony_ci auto intData = [=] { return SkTAddOffset<const int>(uniformData, v.offset); }; 240cb93a386Sopenharmony_ci switch (v.type) { 241cb93a386Sopenharmony_ci case Type::kFloat: pdman.set1fv(handle, v.count, floatData()); break; 242cb93a386Sopenharmony_ci case Type::kFloat2: pdman.set2fv(handle, v.count, floatData()); break; 243cb93a386Sopenharmony_ci case Type::kFloat3: pdman.set3fv(handle, v.count, floatData()); break; 244cb93a386Sopenharmony_ci case Type::kFloat4: pdman.set4fv(handle, v.count, floatData()); break; 245cb93a386Sopenharmony_ci 246cb93a386Sopenharmony_ci case Type::kFloat2x2: pdman.setMatrix2fv(handle, v.count, floatData()); break; 247cb93a386Sopenharmony_ci case Type::kFloat3x3: pdman.setMatrix3fv(handle, v.count, floatData()); break; 248cb93a386Sopenharmony_ci case Type::kFloat4x4: pdman.setMatrix4fv(handle, v.count, floatData()); break; 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci case Type::kInt: pdman.set1iv(handle, v.count, intData()); break; 251cb93a386Sopenharmony_ci case Type::kInt2: pdman.set2iv(handle, v.count, intData()); break; 252cb93a386Sopenharmony_ci case Type::kInt3: pdman.set3iv(handle, v.count, intData()); break; 253cb93a386Sopenharmony_ci case Type::kInt4: pdman.set4iv(handle, v.count, intData()); break; 254cb93a386Sopenharmony_ci 255cb93a386Sopenharmony_ci default: 256cb93a386Sopenharmony_ci SkDEBUGFAIL("Unsupported uniform type"); 257cb93a386Sopenharmony_ci break; 258cb93a386Sopenharmony_ci } 259cb93a386Sopenharmony_ci } 260cb93a386Sopenharmony_ci } 261cb93a386Sopenharmony_ci 262cb93a386Sopenharmony_ci std::vector<UniformHandle> fUniformHandles; 263cb93a386Sopenharmony_ci}; 264cb93a386Sopenharmony_ci 265cb93a386Sopenharmony_cistd::unique_ptr<GrSkSLFP> GrSkSLFP::MakeWithData( 266cb93a386Sopenharmony_ci sk_sp<SkRuntimeEffect> effect, 267cb93a386Sopenharmony_ci const char* name, 268cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> inputFP, 269cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> destColorFP, 270cb93a386Sopenharmony_ci sk_sp<SkData> uniforms, 271cb93a386Sopenharmony_ci SkSpan<std::unique_ptr<GrFragmentProcessor>> childFPs) { 272cb93a386Sopenharmony_ci if (uniforms->size() != effect->uniformSize()) { 273cb93a386Sopenharmony_ci return nullptr; 274cb93a386Sopenharmony_ci } 275cb93a386Sopenharmony_ci size_t uniformSize = uniforms->size(); 276cb93a386Sopenharmony_ci size_t uniformFlagSize = effect->uniforms().size() * sizeof(UniformFlags); 277cb93a386Sopenharmony_ci std::unique_ptr<GrSkSLFP> fp(new (uniformSize + uniformFlagSize) 278cb93a386Sopenharmony_ci GrSkSLFP(std::move(effect), name, OptFlags::kNone)); 279cb93a386Sopenharmony_ci sk_careful_memcpy(fp->uniformData(), uniforms->data(), uniformSize); 280cb93a386Sopenharmony_ci for (auto& childFP : childFPs) { 281cb93a386Sopenharmony_ci fp->addChild(std::move(childFP), /*mergeOptFlags=*/true); 282cb93a386Sopenharmony_ci } 283cb93a386Sopenharmony_ci if (inputFP) { 284cb93a386Sopenharmony_ci fp->setInput(std::move(inputFP)); 285cb93a386Sopenharmony_ci } 286cb93a386Sopenharmony_ci if (destColorFP) { 287cb93a386Sopenharmony_ci fp->setDestColorFP(std::move(destColorFP)); 288cb93a386Sopenharmony_ci } 289cb93a386Sopenharmony_ci return fp; 290cb93a386Sopenharmony_ci} 291cb93a386Sopenharmony_ci 292cb93a386Sopenharmony_ciGrSkSLFP::GrSkSLFP(sk_sp<SkRuntimeEffect> effect, const char* name, OptFlags optFlags) 293cb93a386Sopenharmony_ci : INHERITED(kGrSkSLFP_ClassID, 294cb93a386Sopenharmony_ci static_cast<OptimizationFlags>(optFlags) | 295cb93a386Sopenharmony_ci (effect->getFilterColorProgram() 296cb93a386Sopenharmony_ci ? kConstantOutputForConstantInput_OptimizationFlag 297cb93a386Sopenharmony_ci : kNone_OptimizationFlags)) 298cb93a386Sopenharmony_ci , fEffect(std::move(effect)) 299cb93a386Sopenharmony_ci , fName(name) 300cb93a386Sopenharmony_ci , fUniformSize(SkToU32(fEffect->uniformSize())) { 301cb93a386Sopenharmony_ci memset(this->uniformFlags(), 0, fEffect->uniforms().size() * sizeof(UniformFlags)); 302cb93a386Sopenharmony_ci if (fEffect->usesSampleCoords()) { 303cb93a386Sopenharmony_ci this->setUsesSampleCoordsDirectly(); 304cb93a386Sopenharmony_ci } 305cb93a386Sopenharmony_ci if (fEffect->allowBlender()) { 306cb93a386Sopenharmony_ci this->setIsBlendFunction(); 307cb93a386Sopenharmony_ci } 308cb93a386Sopenharmony_ci} 309cb93a386Sopenharmony_ci 310cb93a386Sopenharmony_ciGrSkSLFP::GrSkSLFP(const GrSkSLFP& other) 311cb93a386Sopenharmony_ci : INHERITED(other) 312cb93a386Sopenharmony_ci , fEffect(other.fEffect) 313cb93a386Sopenharmony_ci , fName(other.fName) 314cb93a386Sopenharmony_ci , fUniformSize(other.fUniformSize) 315cb93a386Sopenharmony_ci , fInputChildIndex(other.fInputChildIndex) { 316cb93a386Sopenharmony_ci sk_careful_memcpy(this->uniformFlags(), 317cb93a386Sopenharmony_ci other.uniformFlags(), 318cb93a386Sopenharmony_ci fEffect->uniforms().size() * sizeof(UniformFlags)); 319cb93a386Sopenharmony_ci sk_careful_memcpy(this->uniformData(), other.uniformData(), fUniformSize); 320cb93a386Sopenharmony_ci} 321cb93a386Sopenharmony_ci 322cb93a386Sopenharmony_civoid GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child, bool mergeOptFlags) { 323cb93a386Sopenharmony_ci SkASSERTF(fInputChildIndex == -1, "all addChild calls must happen before setInput"); 324cb93a386Sopenharmony_ci SkASSERTF(fDestColorChildIndex == -1, "all addChild calls must happen before setDestColorFP"); 325cb93a386Sopenharmony_ci int childIndex = this->numChildProcessors(); 326cb93a386Sopenharmony_ci SkASSERT((size_t)childIndex < fEffect->fSampleUsages.size()); 327cb93a386Sopenharmony_ci if (mergeOptFlags) { 328cb93a386Sopenharmony_ci this->mergeOptimizationFlags(ProcessorOptimizationFlags(child.get())); 329cb93a386Sopenharmony_ci } 330cb93a386Sopenharmony_ci this->registerChild(std::move(child), fEffect->fSampleUsages[childIndex]); 331cb93a386Sopenharmony_ci} 332cb93a386Sopenharmony_ci 333cb93a386Sopenharmony_civoid GrSkSLFP::setInput(std::unique_ptr<GrFragmentProcessor> input) { 334cb93a386Sopenharmony_ci SkASSERTF(fInputChildIndex == -1, "setInput should not be called more than once"); 335cb93a386Sopenharmony_ci fInputChildIndex = this->numChildProcessors(); 336cb93a386Sopenharmony_ci SkASSERT((size_t)fInputChildIndex >= fEffect->fSampleUsages.size()); 337cb93a386Sopenharmony_ci this->mergeOptimizationFlags(ProcessorOptimizationFlags(input.get())); 338cb93a386Sopenharmony_ci this->registerChild(std::move(input), SkSL::SampleUsage::PassThrough()); 339cb93a386Sopenharmony_ci} 340cb93a386Sopenharmony_ci 341cb93a386Sopenharmony_civoid GrSkSLFP::setDestColorFP(std::unique_ptr<GrFragmentProcessor> destColorFP) { 342cb93a386Sopenharmony_ci SkASSERTF(fEffect->allowBlender(), "dest colors are only used by blend effects"); 343cb93a386Sopenharmony_ci SkASSERTF(fDestColorChildIndex == -1, "setDestColorFP should not be called more than once"); 344cb93a386Sopenharmony_ci fDestColorChildIndex = this->numChildProcessors(); 345cb93a386Sopenharmony_ci SkASSERT((size_t)fDestColorChildIndex >= fEffect->fSampleUsages.size()); 346cb93a386Sopenharmony_ci this->mergeOptimizationFlags(ProcessorOptimizationFlags(destColorFP.get())); 347cb93a386Sopenharmony_ci this->registerChild(std::move(destColorFP), SkSL::SampleUsage::PassThrough()); 348cb93a386Sopenharmony_ci} 349cb93a386Sopenharmony_ci 350cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor::ProgramImpl> GrSkSLFP::onMakeProgramImpl() const { 351cb93a386Sopenharmony_ci return std::make_unique<Impl>(); 352cb93a386Sopenharmony_ci} 353cb93a386Sopenharmony_ci 354cb93a386Sopenharmony_ciSkString GrSkSLFP::getShaderDfxInfo() const { 355cb93a386Sopenharmony_ci const UniformFlags* flags = this->uniformFlags(); 356cb93a386Sopenharmony_ci const uint8_t* uniformData = this->uniformData(); 357cb93a386Sopenharmony_ci size_t uniformCount = fEffect->uniforms().size(); 358cb93a386Sopenharmony_ci auto iter = fEffect->uniforms().begin(); 359cb93a386Sopenharmony_ci SkString specials; 360cb93a386Sopenharmony_ci for (size_t i = 0; i < uniformCount; ++i, ++iter) { 361cb93a386Sopenharmony_ci bool specialize = flags[i] & kSpecialize_Flag; 362cb93a386Sopenharmony_ci specials.appendf("_%d", specialize); 363cb93a386Sopenharmony_ci if (specialize) { 364cb93a386Sopenharmony_ci specials.appendf("("); 365cb93a386Sopenharmony_ci const uint8_t* bytes = reinterpret_cast<const uint8_t*>(uniformData + iter->offset); 366cb93a386Sopenharmony_ci uint32_t numBytes = iter->sizeInBytes(); 367cb93a386Sopenharmony_ci for (; numBytes --> 0; bytes++) { 368cb93a386Sopenharmony_ci specials.appendf("%X_", *bytes); 369cb93a386Sopenharmony_ci } 370cb93a386Sopenharmony_ci specials.appendf("%s)", iter->name.c_str()); 371cb93a386Sopenharmony_ci } 372cb93a386Sopenharmony_ci } 373cb93a386Sopenharmony_ci SkString format; 374cb93a386Sopenharmony_ci format.printf("ShaderDfx_GrSkSLFP_%s_%X_%d_%s", name(), fEffect->hash(), fUniformSize, specials.c_str()); 375cb93a386Sopenharmony_ci return format; 376cb93a386Sopenharmony_ci} 377cb93a386Sopenharmony_ci 378cb93a386Sopenharmony_civoid GrSkSLFP::onAddToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const { 379cb93a386Sopenharmony_ci // In the unlikely event of a hash collision, we also include the uniform size in the key. 380cb93a386Sopenharmony_ci // That ensures that we will (at worst) use the wrong program, but one that expects the same 381cb93a386Sopenharmony_ci // amount of uniform data. 382cb93a386Sopenharmony_ci b->add32(fEffect->hash()); 383cb93a386Sopenharmony_ci b->add32(fUniformSize); 384cb93a386Sopenharmony_ci 385cb93a386Sopenharmony_ci const UniformFlags* flags = this->uniformFlags(); 386cb93a386Sopenharmony_ci const uint8_t* uniformData = this->uniformData(); 387cb93a386Sopenharmony_ci size_t uniformCount = fEffect->uniforms().size(); 388cb93a386Sopenharmony_ci auto iter = fEffect->uniforms().begin(); 389cb93a386Sopenharmony_ci 390cb93a386Sopenharmony_ci for (size_t i = 0; i < uniformCount; ++i, ++iter) { 391cb93a386Sopenharmony_ci bool specialize = flags[i] & kSpecialize_Flag; 392cb93a386Sopenharmony_ci b->addBool(specialize, "specialize"); 393cb93a386Sopenharmony_ci if (specialize) { 394cb93a386Sopenharmony_ci b->addBytes(iter->sizeInBytes(), uniformData + iter->offset, iter->name.c_str()); 395cb93a386Sopenharmony_ci } 396cb93a386Sopenharmony_ci } 397cb93a386Sopenharmony_ci} 398cb93a386Sopenharmony_ci 399cb93a386Sopenharmony_cibool GrSkSLFP::onIsEqual(const GrFragmentProcessor& other) const { 400cb93a386Sopenharmony_ci const GrSkSLFP& sk = other.cast<GrSkSLFP>(); 401cb93a386Sopenharmony_ci const size_t uniformFlagSize = fEffect->uniforms().size() * sizeof(UniformFlags); 402cb93a386Sopenharmony_ci return fEffect->hash() == sk.fEffect->hash() && 403cb93a386Sopenharmony_ci fEffect->uniforms().size() == sk.fEffect->uniforms().size() && 404cb93a386Sopenharmony_ci fUniformSize == sk.fUniformSize && 405cb93a386Sopenharmony_ci !sk_careful_memcmp( 406cb93a386Sopenharmony_ci this->uniformData(), sk.uniformData(), fUniformSize + uniformFlagSize); 407cb93a386Sopenharmony_ci} 408cb93a386Sopenharmony_ci 409cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> GrSkSLFP::clone() const { 410cb93a386Sopenharmony_ci return std::unique_ptr<GrFragmentProcessor>(new (UniformPayloadSize(fEffect.get())) 411cb93a386Sopenharmony_ci GrSkSLFP(*this)); 412cb93a386Sopenharmony_ci} 413cb93a386Sopenharmony_ci 414cb93a386Sopenharmony_ciSkPMColor4f GrSkSLFP::constantOutputForConstantInput(const SkPMColor4f& inputColor) const { 415cb93a386Sopenharmony_ci const SkFilterColorProgram* program = fEffect->getFilterColorProgram(); 416cb93a386Sopenharmony_ci SkASSERT(program); 417cb93a386Sopenharmony_ci 418cb93a386Sopenharmony_ci auto evalChild = [&](int index, SkPMColor4f color) { 419cb93a386Sopenharmony_ci return ConstantOutputForConstantInput(this->childProcessor(index), color); 420cb93a386Sopenharmony_ci }; 421cb93a386Sopenharmony_ci 422cb93a386Sopenharmony_ci SkPMColor4f color = (fInputChildIndex >= 0) 423cb93a386Sopenharmony_ci ? ConstantOutputForConstantInput( 424cb93a386Sopenharmony_ci this->childProcessor(fInputChildIndex), inputColor) 425cb93a386Sopenharmony_ci : inputColor; 426cb93a386Sopenharmony_ci return program->eval(color, this->uniformData(), evalChild); 427cb93a386Sopenharmony_ci} 428cb93a386Sopenharmony_ci 429cb93a386Sopenharmony_ci/**************************************************************************************************/ 430cb93a386Sopenharmony_ci 431cb93a386Sopenharmony_ciGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSkSLFP); 432cb93a386Sopenharmony_ci 433cb93a386Sopenharmony_ci#if GR_TEST_UTILS 434cb93a386Sopenharmony_ci 435cb93a386Sopenharmony_ci#include "include/effects/SkOverdrawColorFilter.h" 436cb93a386Sopenharmony_ci#include "src/core/SkColorFilterBase.h" 437cb93a386Sopenharmony_ci 438cb93a386Sopenharmony_ciextern const char* SKSL_OVERDRAW_SRC; 439cb93a386Sopenharmony_ci 440cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d) { 441cb93a386Sopenharmony_ci SkColor colors[SkOverdrawColorFilter::kNumColors]; 442cb93a386Sopenharmony_ci for (SkColor& c : colors) { 443cb93a386Sopenharmony_ci c = d->fRandom->nextU(); 444cb93a386Sopenharmony_ci } 445cb93a386Sopenharmony_ci auto filter = SkOverdrawColorFilter::MakeWithSkColors(colors); 446cb93a386Sopenharmony_ci auto [success, fp] = as_CFB(filter)->asFragmentProcessor(/*inputFP=*/nullptr, d->context(), 447cb93a386Sopenharmony_ci GrColorInfo{}); 448cb93a386Sopenharmony_ci SkASSERT(success); 449cb93a386Sopenharmony_ci return std::move(fp); 450cb93a386Sopenharmony_ci} 451cb93a386Sopenharmony_ci 452cb93a386Sopenharmony_ci#endif 453