blob: e6b1f26e8452f00a32a3064d45d731ad62ffb29d [file] [log] [blame]
Ethan Nicholas00543112018-07-31 09:44:36 -04001/*
2 * Copyright 2018 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/effects/GrSkSLFP.h"
Robert Phillips1efecea2019-02-15 16:58:40 -05009
Brian Osmanee426f22020-01-02 11:55:24 -050010#include "include/effects/SkRuntimeEffect.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/private/GrContext_Base.h"
Brian Osman70ae91f2021-06-10 14:27:53 -040012#include "include/private/SkSLString.h"
Brian Osman10423342021-05-12 16:53:19 -040013#include "src/core/SkRuntimeEffectPriv.h"
Brian Osmanc18a6452021-03-22 11:44:03 -040014#include "src/core/SkVM.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/GrBaseContextPriv.h"
Brian Salomonf7f54332020-07-28 09:23:35 -040016#include "src/gpu/GrColorInfo.h"
Greg Daniel456f9b52020-03-05 19:14:18 +000017#include "src/gpu/GrTexture.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/sksl/SkSLUtil.h"
John Stiles3738ef52021-04-13 10:41:57 -040019#include "src/sksl/codegen/SkSLPipelineStageCodeGenerator.h"
Brian Osman690b6f32021-02-05 16:30:34 -050020#include "src/sksl/ir/SkSLVarDeclarations.h"
Robert Phillips1efecea2019-02-15 16:58:40 -050021
Mike Kleinc0bd9f92019-04-23 12:05:21 -050022#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
23#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
24#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
Ethan Nicholas00543112018-07-31 09:44:36 -040025
Brian Salomon3176e862021-08-09 11:23:04 -040026class GrGLSLSkSLFP : public GrFragmentProcessor::ProgramImpl {
Ethan Nicholaseace9352018-10-15 20:09:54 +000027public:
Ethan Nicholaseace9352018-10-15 20:09:54 +000028 void emitCode(EmitArgs& args) override {
Brian Osman690b6f32021-02-05 16:30:34 -050029 const GrSkSLFP& fp = args.fFp.cast<GrSkSLFP>();
30 const SkSL::Program& program = *fp.fEffect->fBaseProgram;
31
Brian Osman690b6f32021-02-05 16:30:34 -050032 class FPCallbacks : public SkSL::PipelineStage::Callbacks {
33 public:
Brian Osmance585022021-04-15 15:39:03 -040034 FPCallbacks(GrGLSLSkSLFP* self,
35 EmitArgs& args,
36 const char* inputColor,
Brian Osman70ae91f2021-06-10 14:27:53 -040037 const SkSL::Context& context,
38 const uint8_t* uniformData,
39 const GrSkSLFP::UniformFlags* uniformFlags)
40 : fSelf(self)
41 , fArgs(args)
42 , fInputColor(inputColor)
43 , fContext(context)
44 , fUniformData(uniformData)
45 , fUniformFlags(uniformFlags) {}
Brian Osman690b6f32021-02-05 16:30:34 -050046
47 using String = SkSL::String;
48
49 String declareUniform(const SkSL::VarDeclaration* decl) override {
50 const SkSL::Variable& var = decl->var();
51 if (var.type().isOpaque()) {
Brian Osman14d00962021-04-02 17:04:35 -040052 // Nothing to do. The only opaque types we should see are children, and those
53 // are handled specially, above.
54 SkASSERT(var.type().isEffectChild());
Brian Osman690b6f32021-02-05 16:30:34 -050055 return String(var.name());
56 }
57
58 const SkSL::Type* type = &var.type();
Brian Osman70ae91f2021-06-10 14:27:53 -040059 size_t sizeInBytes = type->slotCount() * sizeof(float);
60 const float* floatData = reinterpret_cast<const float*>(fUniformData);
61 const int* intData = reinterpret_cast<const int*>(fUniformData);
62 fUniformData += sizeInBytes;
63
Brian Osman690b6f32021-02-05 16:30:34 -050064 bool isArray = false;
65 if (type->isArray()) {
66 type = &type->componentType();
67 isArray = true;
68 }
69
70 GrSLType gpuType;
71 SkAssertResult(SkSL::type_to_grsltype(fContext, *type, &gpuType));
Brian Osman70ae91f2021-06-10 14:27:53 -040072
73 if (*fUniformFlags++ & GrSkSLFP::kSpecialize_Flag) {
74 SkASSERTF(!isArray, "specializing array uniforms is not allowed");
75 String value = GrGLSLTypeString(gpuType);
76 value.append("(");
77
78 bool isFloat = GrSLTypeIsFloatType(gpuType);
79 size_t slots = type->slotCount();
80 for (size_t i = 0; i < slots; ++i) {
81 value.append(isFloat ? SkSL::to_string(floatData[i])
82 : SkSL::to_string(intData[i]));
83 value.append(",");
84 }
85 value.back() = ')';
86 return value;
87 }
88
Brian Osman690b6f32021-02-05 16:30:34 -050089 const char* uniformName = nullptr;
90 auto handle =
91 fArgs.fUniformHandler->addUniformArray(&fArgs.fFp.cast<GrSkSLFP>(),
92 kFragment_GrShaderFlag,
93 gpuType,
94 SkString(var.name()).c_str(),
95 isArray ? var.type().columns() : 0,
96 &uniformName);
97 fSelf->fUniformHandles.push_back(handle);
98 return String(uniformName);
99 }
100
Brian Osman55761ae2021-02-09 16:52:53 -0500101 String getMangledName(const char* name) override {
102 return String(fArgs.fFragBuilder->getMangledFunctionName(name).c_str());
103 }
104
105 void defineFunction(const char* decl, const char* body, bool isMain) override {
106 if (isMain) {
107 fArgs.fFragBuilder->codeAppend(body);
Brian Osman690b6f32021-02-05 16:30:34 -0500108 } else {
Brian Osman55761ae2021-02-09 16:52:53 -0500109 fArgs.fFragBuilder->emitFunction(decl, body);
Brian Osman690b6f32021-02-05 16:30:34 -0500110 }
111 }
112
Brian Osman8e756f32021-02-10 10:19:27 -0500113 void defineStruct(const char* definition) override {
114 fArgs.fFragBuilder->definitionAppend(definition);
115 }
116
Brian Osman5e603c32021-02-17 15:39:06 -0500117 void declareGlobal(const char* declaration) override {
118 fArgs.fFragBuilder->definitionAppend(declaration);
119 }
120
John Stilesd9a56b92021-07-23 15:50:39 -0400121 String sampleShader(int index, String coords) override {
Brian Osman4d571112021-04-27 09:10:10 -0400122 // If the child was sampled using the coords passed to main (and they are never
123 // modified), then we will have marked the child as PassThrough. The code generator
124 // doesn't know that, and still supplies coords. Inside invokeChild, we assert that
125 // any coords passed for a PassThrough child match args.fSampleCoords exactly.
126 //
127 // Normally, this is valid. Here, we *copied* the sample coords to a local variable
128 // (so that they're mutable in the runtime effect SkSL). Thus, the coords string we
129 // get here is the name of the local copy, and fSampleCoords still points to the
130 // unmodified original (which might be a varying, for example).
131 // To prevent the assert, we pass the empty string in this case. Note that for
132 // children sampled like this, invokeChild doesn't even use the coords parameter,
133 // except for that assert.
134 const GrFragmentProcessor* child = fArgs.fFp.childProcessor(index);
Brian Osman56b61072021-06-29 13:12:40 -0400135 if (child && child->sampleUsage().isPassThrough()) {
Brian Osman4d571112021-04-27 09:10:10 -0400136 coords.clear();
137 }
John Stilesd9a56b92021-07-23 15:50:39 -0400138 return String(fSelf->invokeChild(index, fInputColor, fArgs, coords).c_str());
Brian Osman690b6f32021-02-05 16:30:34 -0500139 }
140
John Stiles8050a4b2021-07-23 15:50:20 -0400141 String sampleColorFilter(int index, String color) override {
142 return String(fSelf->invokeChild(index,
143 color.empty() ? fInputColor : color.c_str(),
144 fArgs)
145 .c_str());
146 }
147
John Stiles2955c262021-07-23 15:51:05 -0400148 String sampleBlender(int index, String src, String dst) override {
John Stilesce9a5c92021-07-30 11:20:19 -0400149 if (!fSelf->childProcessor(index)) {
150 return String::printf("blend_src_over(%s, %s)", src.c_str(), dst.c_str());
151 }
152 return String(fSelf->invokeChild(index, src.c_str(), dst.c_str(), fArgs).c_str());
John Stiles2955c262021-07-23 15:51:05 -0400153 }
154
Brian Osman70ae91f2021-06-10 14:27:53 -0400155 GrGLSLSkSLFP* fSelf;
156 EmitArgs& fArgs;
157 const char* fInputColor;
158 const SkSL::Context& fContext;
159 const uint8_t* fUniformData;
160 const GrSkSLFP::UniformFlags* fUniformFlags;
161 int fUniformIndex = 0;
Brian Osman690b6f32021-02-05 16:30:34 -0500162 };
163
Brian Osmanb2cb8172021-06-15 14:36:17 -0400164 // If we have an input child, we invoke it now, and make the result of that be the "input
165 // color" for all other purposes later (eg, the default passed via sample calls, etc.)
166 if (fp.fInputChildIndex >= 0) {
167 args.fFragBuilder->codeAppendf("%s = %s;\n",
168 args.fInputColor,
169 this->invokeChild(fp.fInputChildIndex, args).c_str());
170 }
171
John Stiles21c2af22021-07-29 11:42:55 -0400172 if (fp.fEffect->allowBlender()) {
173 // If we have an dest-color child, we invoke it now, and make the result of that be the
174 // "dest color" for all other purposes later.
175 if (fp.fDestColorChildIndex >= 0) {
176 args.fFragBuilder->codeAppendf(
177 "%s = %s;\n",
178 args.fDestColor,
179 this->invokeChild(fp.fDestColorChildIndex, args.fDestColor, args).c_str());
180 }
181 } else {
182 // We're not making a blender, so we don't expect a dest-color child FP to exist.
183 SkASSERT(fp.fDestColorChildIndex < 0);
184 }
185
Brian Osmance585022021-04-15 15:39:03 -0400186 // Snap off a global copy of the input color at the start of main. We need this when
187 // we call child processors (particularly from helper functions, which can't "see" the
188 // parameter to main). Even from within main, if the code mutates the parameter, calls to
189 // sample should still be passing the original color (by default).
Brian Osman04d79fc2021-07-02 13:25:35 -0400190 SkString inputColorName;
191 if (fp.fEffect->samplesOutsideMain()) {
192 GrShaderVar inputColorCopy(args.fFragBuilder->getMangledFunctionName("inColor"),
193 kHalf4_GrSLType);
194 args.fFragBuilder->declareGlobal(inputColorCopy);
195 inputColorName = inputColorCopy.getName();
196 args.fFragBuilder->codeAppendf("%s = %s;\n", inputColorName.c_str(), args.fInputColor);
197 } else {
198 inputColorName = args.fFragBuilder->newTmpVarName("inColor");
199 args.fFragBuilder->codeAppendf(
200 "half4 %s = %s;\n", inputColorName.c_str(), args.fInputColor);
201 }
Brian Osman690b6f32021-02-05 16:30:34 -0500202
Brian Osman8cdf28f2021-05-24 09:52:39 -0400203 // Copy the incoming coords to a local variable. Code in main might modify the coords
204 // parameter. fSampleCoord could be a varying, so writes to it would be illegal.
John Stiles9b170c62021-06-18 10:14:14 -0400205 const char* coords = "float2(0)";
206 SkString coordsVarName;
Brian Salomon66b500a2021-08-02 12:37:14 -0400207 if (fp.usesSampleCoordsDirectly()) {
John Stiles9b170c62021-06-18 10:14:14 -0400208 coordsVarName = args.fFragBuilder->newTmpVarName("coords");
209 coords = coordsVarName.c_str();
Brian Osman690b6f32021-02-05 16:30:34 -0500210 args.fFragBuilder->codeAppendf("float2 %s = %s;\n", coords, args.fSampleCoord);
Brian Osmanb4ce9442020-11-11 09:18:02 -0500211 }
Brian Osman690b6f32021-02-05 16:30:34 -0500212
Brian Osman70ae91f2021-06-10 14:27:53 -0400213 FPCallbacks callbacks(this,
214 args,
Brian Osman04d79fc2021-07-02 13:25:35 -0400215 inputColorName.c_str(),
Brian Osman70ae91f2021-06-10 14:27:53 -0400216 *program.fContext,
217 fp.uniformData(),
218 fp.uniformFlags());
219 SkSL::PipelineStage::ConvertProgram(
John Stiles21c2af22021-07-29 11:42:55 -0400220 program, coords, args.fInputColor, args.fDestColor, &callbacks);
Ethan Nicholasce008112018-08-30 09:19:50 -0400221 }
222
Ethan Nicholaseace9352018-10-15 20:09:54 +0000223 void onSetData(const GrGLSLProgramDataManager& pdman,
224 const GrFragmentProcessor& _proc) override {
Brian Osmand18967c2021-04-01 09:56:07 -0400225 using Type = SkRuntimeEffect::Uniform::Type;
Brian Osmand927bd22019-12-18 11:23:12 -0500226 size_t uniIndex = 0;
Ethan Nicholaseace9352018-10-15 20:09:54 +0000227 const GrSkSLFP& outer = _proc.cast<GrSkSLFP>();
Brian Osman70ae91f2021-06-10 14:27:53 -0400228 const uint8_t* uniformData = outer.uniformData();
229 const GrSkSLFP::UniformFlags* uniformFlags = outer.uniformFlags();
Brian Osmana4b91692020-08-10 14:26:16 -0400230 for (const auto& v : outer.fEffect->uniforms()) {
Brian Osman70ae91f2021-06-10 14:27:53 -0400231 if (*uniformFlags++ & GrSkSLFP::kSpecialize_Flag) {
232 continue;
233 }
Brian Osmand18967c2021-04-01 09:56:07 -0400234 const UniformHandle handle = fUniformHandles[uniIndex++];
235 auto floatData = [=] { return SkTAddOffset<const float>(uniformData, v.offset); };
236 auto intData = [=] { return SkTAddOffset<const int>(uniformData, v.offset); };
Brian Osmand76d1862021-02-03 14:48:41 -0500237 switch (v.type) {
Brian Osmand18967c2021-04-01 09:56:07 -0400238 case Type::kFloat: pdman.set1fv(handle, v.count, floatData()); break;
239 case Type::kFloat2: pdman.set2fv(handle, v.count, floatData()); break;
240 case Type::kFloat3: pdman.set3fv(handle, v.count, floatData()); break;
241 case Type::kFloat4: pdman.set4fv(handle, v.count, floatData()); break;
242
243 case Type::kFloat2x2: pdman.setMatrix2fv(handle, v.count, floatData()); break;
244 case Type::kFloat3x3: pdman.setMatrix3fv(handle, v.count, floatData()); break;
245 case Type::kFloat4x4: pdman.setMatrix4fv(handle, v.count, floatData()); break;
246
247 case Type::kInt: pdman.set1iv(handle, v.count, intData()); break;
248 case Type::kInt2: pdman.set2iv(handle, v.count, intData()); break;
249 case Type::kInt3: pdman.set3iv(handle, v.count, intData()); break;
250 case Type::kInt4: pdman.set4iv(handle, v.count, intData()); break;
251
Ethan Nicholasc1c686b2019-04-02 17:30:23 -0400252 default:
Brian Osmand927bd22019-12-18 11:23:12 -0500253 SkDEBUGFAIL("Unsupported uniform type");
254 break;
Ethan Nicholas222e2752018-10-11 11:21:34 -0400255 }
Ethan Nicholas222e2752018-10-11 11:21:34 -0400256 }
257 }
Ethan Nicholaseace9352018-10-15 20:09:54 +0000258
Ethan Nicholaseace9352018-10-15 20:09:54 +0000259 std::vector<UniformHandle> fUniformHandles;
260};
261
Brian Osmanb2cb8172021-06-15 14:36:17 -0400262std::unique_ptr<GrSkSLFP> GrSkSLFP::MakeWithData(
263 sk_sp<SkRuntimeEffect> effect,
264 const char* name,
265 std::unique_ptr<GrFragmentProcessor> inputFP,
John Stilesa6648592021-07-19 18:11:09 -0400266 std::unique_ptr<GrFragmentProcessor> destColorFP,
Brian Osmanb2cb8172021-06-15 14:36:17 -0400267 sk_sp<SkData> uniforms,
268 SkSpan<std::unique_ptr<GrFragmentProcessor>> childFPs) {
Brian Osmana4b91692020-08-10 14:26:16 -0400269 if (uniforms->size() != effect->uniformSize()) {
Brian Osman9bfd5952020-02-05 10:51:44 -0500270 return nullptr;
271 }
Brian Osman681e4092021-06-03 14:26:07 -0400272 size_t uniformSize = uniforms->size();
Brian Osman70ae91f2021-06-10 14:27:53 -0400273 size_t uniformFlagSize = effect->uniforms().count() * sizeof(UniformFlags);
274 std::unique_ptr<GrSkSLFP> fp(new (uniformSize + uniformFlagSize)
John Stiles02b6f6f2021-07-30 11:06:55 -0400275 GrSkSLFP(std::move(effect), name, OptFlags::kNone));
Brian Osman1f5ee0d2021-06-10 14:40:40 -0400276 sk_careful_memcpy(fp->uniformData(), uniforms->data(), uniformSize);
Brian Osmanb2cb8172021-06-15 14:36:17 -0400277 for (auto& childFP : childFPs) {
Brian Osman9204ca62021-06-25 12:35:16 -0400278 fp->addChild(std::move(childFP), /*mergeOptFlags=*/true);
Brian Osmanb2cb8172021-06-15 14:36:17 -0400279 }
280 if (inputFP) {
281 fp->setInput(std::move(inputFP));
282 }
John Stilesa6648592021-07-19 18:11:09 -0400283 if (destColorFP) {
284 fp->setDestColorFP(std::move(destColorFP));
285 }
Brian Osman1f5ee0d2021-06-10 14:40:40 -0400286 return fp;
Ethan Nicholasa70693b2019-03-04 13:07:36 -0500287}
288
Brian Osman171fba72021-06-16 17:10:21 -0400289GrSkSLFP::GrSkSLFP(sk_sp<SkRuntimeEffect> effect, const char* name, OptFlags optFlags)
Brian Osmane384c062021-06-04 14:09:51 -0400290 : INHERITED(kGrSkSLFP_ClassID,
Brian Osman171fba72021-06-16 17:10:21 -0400291 static_cast<OptimizationFlags>(optFlags) |
292 (effect->getFilterColorProgram()
293 ? kConstantOutputForConstantInput_OptimizationFlag
294 : kNone_OptimizationFlags))
Brian Osmane384c062021-06-04 14:09:51 -0400295 , fEffect(std::move(effect))
296 , fName(name)
Brian Osmanb2cb8172021-06-15 14:36:17 -0400297 , fUniformSize(SkToU32(fEffect->uniformSize())) {
Brian Osman70ae91f2021-06-10 14:27:53 -0400298 memset(this->uniformFlags(), 0, fEffect->uniforms().count() * sizeof(UniformFlags));
Brian Osmane384c062021-06-04 14:09:51 -0400299 if (fEffect->usesSampleCoords()) {
300 this->setUsesSampleCoordsDirectly();
301 }
John Stiles02b6f6f2021-07-30 11:06:55 -0400302 if (fEffect->allowBlender()) {
303 this->setIsBlendFunction();
304 }
Brian Osmane384c062021-06-04 14:09:51 -0400305}
306
Ethan Nicholas00543112018-07-31 09:44:36 -0400307GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
John Stiles307f8f52021-08-09 15:36:59 -0400308 : INHERITED(other)
Brian Osman7b1678a2019-12-16 09:17:25 -0500309 , fEffect(other.fEffect)
Ethan Nicholas00543112018-07-31 09:44:36 -0400310 , fName(other.fName)
Brian Osmanb2cb8172021-06-15 14:36:17 -0400311 , fUniformSize(other.fUniformSize)
312 , fInputChildIndex(other.fInputChildIndex) {
Brian Osman70ae91f2021-06-10 14:27:53 -0400313 sk_careful_memcpy(this->uniformFlags(),
314 other.uniformFlags(),
315 fEffect->uniforms().count() * sizeof(UniformFlags));
Brian Osman681e4092021-06-03 14:26:07 -0400316 sk_careful_memcpy(this->uniformData(), other.uniformData(), fUniformSize);
Ethan Nicholaseace9352018-10-15 20:09:54 +0000317}
Ethan Nicholas00543112018-07-31 09:44:36 -0400318
Brian Osman9204ca62021-06-25 12:35:16 -0400319void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child, bool mergeOptFlags) {
Brian Osmanb2cb8172021-06-15 14:36:17 -0400320 SkASSERTF(fInputChildIndex == -1, "all addChild calls must happen before setInput");
John Stilesa6648592021-07-19 18:11:09 -0400321 SkASSERTF(fDestColorChildIndex == -1, "all addChild calls must happen before setDestColorFP");
Brian Osmanbe1b8372020-06-18 13:40:26 -0400322 int childIndex = this->numChildProcessors();
Brian Osman1298bc42020-06-30 13:39:35 -0400323 SkASSERT((size_t)childIndex < fEffect->fSampleUsages.size());
Brian Osman9204ca62021-06-25 12:35:16 -0400324 if (mergeOptFlags) {
325 this->mergeOptimizationFlags(ProcessorOptimizationFlags(child.get()));
326 }
Brian Osman1298bc42020-06-30 13:39:35 -0400327 this->registerChild(std::move(child), fEffect->fSampleUsages[childIndex]);
Ethan Nicholasce008112018-08-30 09:19:50 -0400328}
329
Brian Osmanb2cb8172021-06-15 14:36:17 -0400330void GrSkSLFP::setInput(std::unique_ptr<GrFragmentProcessor> input) {
331 SkASSERTF(fInputChildIndex == -1, "setInput should not be called more than once");
332 fInputChildIndex = this->numChildProcessors();
John Stilesa6648592021-07-19 18:11:09 -0400333 SkASSERT((size_t)fInputChildIndex >= fEffect->fSampleUsages.size());
Brian Osmanb2cb8172021-06-15 14:36:17 -0400334 this->mergeOptimizationFlags(ProcessorOptimizationFlags(input.get()));
335 this->registerChild(std::move(input), SkSL::SampleUsage::PassThrough());
336}
337
John Stilesa6648592021-07-19 18:11:09 -0400338void GrSkSLFP::setDestColorFP(std::unique_ptr<GrFragmentProcessor> destColorFP) {
339 SkASSERTF(fEffect->allowBlender(), "dest colors are only used by blend effects");
340 SkASSERTF(fDestColorChildIndex == -1, "setDestColorFP should not be called more than once");
341 fDestColorChildIndex = this->numChildProcessors();
342 SkASSERT((size_t)fDestColorChildIndex >= fEffect->fSampleUsages.size());
343 this->mergeOptimizationFlags(ProcessorOptimizationFlags(destColorFP.get()));
344 this->registerChild(std::move(destColorFP), SkSL::SampleUsage::PassThrough());
345}
346
Brian Salomon3176e862021-08-09 11:23:04 -0400347std::unique_ptr<GrFragmentProcessor::ProgramImpl> GrSkSLFP::onMakeProgramImpl() const {
Brian Salomon18ab2032021-02-23 10:07:05 -0500348 return std::make_unique<GrGLSLSkSLFP>();
Greg Danielf4107942019-12-12 01:02:48 +0000349}
350
Brian Salomon13b28732021-08-06 15:33:58 -0400351void GrSkSLFP::onAddToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
Brian Osmana4b91692020-08-10 14:26:16 -0400352 // In the unlikely event of a hash collision, we also include the uniform size in the key.
Brian Osman32253062020-02-05 11:37:08 -0500353 // That ensures that we will (at worst) use the wrong program, but one that expects the same
Brian Osmana4b91692020-08-10 14:26:16 -0400354 // amount of uniform data.
Brian Osman32253062020-02-05 11:37:08 -0500355 b->add32(fEffect->hash());
Brian Osmanb2cb8172021-06-15 14:36:17 -0400356 b->add32(fUniformSize);
Brian Osman70ae91f2021-06-10 14:27:53 -0400357
358 const UniformFlags* flags = this->uniformFlags();
359 const uint8_t* uniformData = this->uniformData();
360 size_t uniformCount = fEffect->uniforms().count();
361 auto iter = fEffect->uniforms().begin();
362
Brian Osmand02d4eb2021-06-23 11:33:16 -0400363 for (size_t i = 0; i < uniformCount; ++i, ++iter) {
Brian Osman70ae91f2021-06-10 14:27:53 -0400364 bool specialize = flags[i] & kSpecialize_Flag;
365 b->addBool(specialize, "specialize");
366 if (specialize) {
367 b->addBytes(iter->sizeInBytes(), uniformData + iter->offset, iter->name.c_str());
368 }
369 }
Ethan Nicholas00543112018-07-31 09:44:36 -0400370}
371
372bool GrSkSLFP::onIsEqual(const GrFragmentProcessor& other) const {
373 const GrSkSLFP& sk = other.cast<GrSkSLFP>();
Brian Osman70ae91f2021-06-10 14:27:53 -0400374 const size_t uniformFlagSize = fEffect->uniforms().count() * sizeof(UniformFlags);
Brian Osman681e4092021-06-03 14:26:07 -0400375 return fEffect->hash() == sk.fEffect->hash() &&
Brian Osman70ae91f2021-06-10 14:27:53 -0400376 fEffect->uniforms().count() == sk.fEffect->uniforms().count() &&
Brian Osman681e4092021-06-03 14:26:07 -0400377 fUniformSize == sk.fUniformSize &&
Brian Osman70ae91f2021-06-10 14:27:53 -0400378 !sk_careful_memcmp(
379 this->uniformData(), sk.uniformData(), fUniformSize + uniformFlagSize);
Ethan Nicholas00543112018-07-31 09:44:36 -0400380}
381
382std::unique_ptr<GrFragmentProcessor> GrSkSLFP::clone() const {
Brian Osman70ae91f2021-06-10 14:27:53 -0400383 return std::unique_ptr<GrFragmentProcessor>(new (UniformPayloadSize(fEffect.get()))
384 GrSkSLFP(*this));
Ethan Nicholas00543112018-07-31 09:44:36 -0400385}
386
Brian Osmanc18a6452021-03-22 11:44:03 -0400387SkPMColor4f GrSkSLFP::constantOutputForConstantInput(const SkPMColor4f& inputColor) const {
Brian Osman10423342021-05-12 16:53:19 -0400388 const SkFilterColorProgram* program = fEffect->getFilterColorProgram();
Brian Osmanc9125aa2021-04-21 09:57:19 -0400389 SkASSERT(program);
Brian Osmanc18a6452021-03-22 11:44:03 -0400390
Brian Osman10423342021-05-12 16:53:19 -0400391 auto evalChild = [&](int index, SkPMColor4f color) {
392 return ConstantOutputForConstantInput(this->childProcessor(index), color);
393 };
Brian Osmanc18a6452021-03-22 11:44:03 -0400394
Brian Osmanb2cb8172021-06-15 14:36:17 -0400395 SkPMColor4f color = (fInputChildIndex >= 0)
396 ? ConstantOutputForConstantInput(
397 this->childProcessor(fInputChildIndex), inputColor)
398 : inputColor;
399 return program->eval(color, this->uniformData(), evalChild);
Brian Osmanc18a6452021-03-22 11:44:03 -0400400}
401
Robert Phillips7f11fb52019-12-03 13:35:19 -0500402/**************************************************************************************************/
Ethan Nicholas00543112018-07-31 09:44:36 -0400403
404GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSkSLFP);
405
406#if GR_TEST_UTILS
407
Mike Kleina73819b2020-04-17 08:26:30 -0500408#include "include/effects/SkOverdrawColorFilter.h"
Mike Reedb11e6272020-06-24 16:56:33 -0400409#include "src/core/SkColorFilterBase.h"
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400410
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400411extern const char* SKSL_OVERDRAW_SRC;
Ethan Nicholas00543112018-07-31 09:44:36 -0400412
Ethan Nicholas00543112018-07-31 09:44:36 -0400413std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d) {
John Stilesa9c9b532020-07-09 17:13:13 -0400414 SkColor colors[SkOverdrawColorFilter::kNumColors];
415 for (SkColor& c : colors) {
416 c = d->fRandom->nextU();
Ethan Nicholas00543112018-07-31 09:44:36 -0400417 }
John Stilesa9c9b532020-07-09 17:13:13 -0400418 auto filter = SkOverdrawColorFilter::MakeWithSkColors(colors);
419 auto [success, fp] = as_CFB(filter)->asFragmentProcessor(/*inputFP=*/nullptr, d->context(),
420 GrColorInfo{});
421 SkASSERT(success);
422 return std::move(fp);
Ethan Nicholas00543112018-07-31 09:44:36 -0400423}
424
425#endif