• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
8 #include "src/gpu/effects/GrSkSLFP.h"
9 
10 #include "include/gpu/GrTexture.h"
11 #include "include/private/GrContext_Base.h"
12 #include "src/gpu/GrBaseContextPriv.h"
13 #include "src/sksl/SkSLUtil.h"
14 
15 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
16 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
17 #include "src/gpu/glsl/GrGLSLProgramBuilder.h"
18 
GrSkSLFPFactory(const char * name,const GrShaderCaps * shaderCaps,const char * sksl,SkSL::Program::Kind kind)19 GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl,
20                                  SkSL::Program::Kind kind)
21         : fKind(kind)
22         , fName(name) {
23     SkSL::Program::Settings settings;
24     settings.fCaps = shaderCaps;
25     fBaseProgram = fCompiler.convertProgram(fKind, SkSL::String(sksl), settings);
26     if (fCompiler.errorCount()) {
27         SkDebugf("%s\n", fCompiler.errorText().c_str());
28     }
29     SkASSERT(fBaseProgram);
30     SkASSERT(!fCompiler.errorCount());
31     for (const auto& e : *fBaseProgram) {
32         if (e.fKind == SkSL::ProgramElement::kVar_Kind) {
33             SkSL::VarDeclarations& v = (SkSL::VarDeclarations&) e;
34             for (const auto& varStatement : v.fVars) {
35                 const SkSL::Variable& var = *((SkSL::VarDeclaration&) *varStatement).fVar;
36                 if (var.fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
37                     fInputVars.push_back(&var);
38                 }
39                 if (var.fModifiers.fLayout.fKey) {
40                     fKeyVars.push_back(&var);
41                 }
42             }
43         }
44     }
45 }
46 
getSpecialization(const SkSL::String & key,const void * inputs,size_t inputSize)47 const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key, const void* inputs,
48                                                         size_t inputSize) {
49     const auto& found = fSpecializations.find(key);
50     if (found != fSpecializations.end()) {
51         return found->second.get();
52     }
53 
54     std::unordered_map<SkSL::String, SkSL::Program::Settings::Value> inputMap;
55     size_t offset = 0;
56     for (const auto& v : fInputVars) {
57         SkSL::String name(v->fName);
58         if (&v->fType == fCompiler.context().fInt_Type.get() ||
59             &v->fType == fCompiler.context().fShort_Type.get()) {
60             offset = SkAlign4(offset);
61             int32_t v = *(int32_t*) (((uint8_t*) inputs) + offset);
62             inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v)));
63             offset += sizeof(int32_t);
64         } else if (&v->fType == fCompiler.context().fFloat_Type.get() ||
65                    &v->fType == fCompiler.context().fHalf_Type.get()) {
66             offset = SkAlign4(offset);
67             float v = *(float*) (((uint8_t*) inputs) + offset);
68             inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v)));
69             offset += sizeof(float);
70         } else if (&v->fType == fCompiler.context().fBool_Type.get()) {
71             bool v = *(((bool*) inputs) + offset);
72             inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v)));
73             offset += sizeof(bool);
74         } else if (&v->fType == fCompiler.context().fFloat4_Type.get() ||
75                    &v->fType == fCompiler.context().fHalf4_Type.get()) {
76             offset = SkAlign4(offset) + sizeof(float) * 4;
77         } else if (&v->fType == fCompiler.context().fFragmentProcessor_Type.get()) {
78             // do nothing
79         } else {
80             printf("can't handle input var: %s\n", SkSL::String(v->fType.fName).c_str());
81             SkASSERT(false);
82         }
83     }
84 
85     std::unique_ptr<SkSL::Program> specialized = fCompiler.specialize(*fBaseProgram, inputMap);
86     bool optimized = fCompiler.optimize(*specialized);
87     if (!optimized) {
88         SkDebugf("%s\n", fCompiler.errorText().c_str());
89         SkASSERT(false);
90     }
91     const SkSL::Program* result = specialized.get();
92     fSpecializations.insert(std::make_pair(key, std::move(specialized)));
93     return result;
94 }
95 
get_ctype(const SkSL::Context & context,const SkSL::Variable & v)96 static SkSL::Layout::CType get_ctype(const SkSL::Context& context, const SkSL::Variable& v) {
97    SkSL::Layout::CType result = v.fModifiers.fLayout.fCType;
98    if (result == SkSL::Layout::CType::kDefault) {
99         if (&v.fType == context.fFloat_Type.get()) {
100             result = SkSL::Layout::CType::kFloat;
101         } else if (&v.fType == context.fFloat4_Type.get()) {
102            result = SkSL::Layout::CType::kSkRect;
103         } else if (&v.fType == context.fHalf4_Type.get()) {
104            result = SkSL::Layout::CType::kSkPMColor;
105         } else if (&v.fType == context.fInt_Type.get()) {
106             result = SkSL::Layout::CType::kInt32;
107         } else if (&v.fType == context.fBool_Type.get()) {
108             result = SkSL::Layout::CType::kBool;
109         } else {
110             return SkSL::Layout::CType::kDefault;
111         }
112     }
113     return result;
114 }
115 
116 class GrGLSLSkSLFP : public GrGLSLFragmentProcessor {
117 public:
GrGLSLSkSLFP(const SkSL::Context * context,const std::vector<const SkSL::Variable * > * inputVars,SkSL::String glsl,std::vector<SkSL::Compiler::FormatArg> formatArgs)118     GrGLSLSkSLFP(const SkSL::Context* context, const std::vector<const SkSL::Variable*>* inputVars,
119                  SkSL::String glsl, std::vector<SkSL::Compiler::FormatArg> formatArgs)
120             : fContext(*context)
121             , fInputVars(*inputVars)
122             , fGLSL(glsl)
123             , fFormatArgs(formatArgs) {}
124 
uniformType(const SkSL::Type & type)125     GrSLType uniformType(const SkSL::Type& type) {
126         if (type == *fContext.fFloat_Type) {
127             return kFloat_GrSLType;
128         } else if (type == *fContext.fHalf_Type) {
129             return kHalf_GrSLType;
130         } else if (type == *fContext.fFloat2_Type) {
131             return kFloat2_GrSLType;
132         } else if (type == *fContext.fHalf2_Type) {
133             return kHalf2_GrSLType;
134         } else if (type == *fContext.fFloat4_Type) {
135             return kFloat4_GrSLType;
136         } else if (type == *fContext.fHalf4_Type) {
137             return kHalf4_GrSLType;
138         } else if (type == *fContext.fFloat4x4_Type) {
139             return kFloat4x4_GrSLType;
140         } else if (type == *fContext.fHalf4x4_Type) {
141             return kHalf4x4_GrSLType;
142         } else if (type == *fContext.fBool_Type) {
143             return kBool_GrSLType;
144         } else if (type == *fContext.fInt_Type) {
145             return kInt_GrSLType;
146         }
147         printf("%s\n", SkSL::String(type.fName).c_str());
148         SK_ABORT("unsupported uniform type");
149     }
150 
emitCode(EmitArgs & args)151     void emitCode(EmitArgs& args) override {
152         for (const auto& v : fInputVars) {
153             if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag && v->fType !=
154                                                                 *fContext.fFragmentProcessor_Type) {
155                 fUniformHandles.push_back(args.fUniformHandler->addUniform(
156                                                                    kFragment_GrShaderFlag,
157                                                                    this->uniformType(v->fType),
158                                                                    SkSL::String(v->fName).c_str()));
159             }
160         }
161         std::vector<SkString> childNames;
162         for (int i = 0; i < this->numChildProcessors(); ++i) {
163             childNames.push_back(SkStringPrintf("_child%d", i));
164             this->invokeChild(i, &childNames[i], args);
165         }
166         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
167         int substringStartIndex = 0;
168         int formatArgIndex = 0;
169         SkString coords = args.fTransformedCoords.count()
170             ? fragBuilder->ensureCoords2D(args.fTransformedCoords[0])
171             : SkString("sk_FragCoord");
172         for (size_t i = 0; i < fGLSL.length(); ++i) {
173             char c = fGLSL[i];
174             if (c == '%') {
175                 fragBuilder->codeAppend(fGLSL.c_str() + substringStartIndex,
176                                         i - substringStartIndex);
177                 ++i;
178                 c = fGLSL[i];
179                 switch (c) {
180                     case 's': {
181                         SkSL::Compiler::FormatArg& arg = fFormatArgs[formatArgIndex++];
182                         switch (arg.fKind) {
183                             case SkSL::Compiler::FormatArg::Kind::kInput:
184                                 fragBuilder->codeAppend(args.fInputColor);
185                                 break;
186                             case SkSL::Compiler::FormatArg::Kind::kOutput:
187                                 fragBuilder->codeAppend(args.fOutputColor);
188                                 break;
189                             case SkSL::Compiler::FormatArg::Kind::kCoordX:
190                                 fragBuilder->codeAppendf("%s.x", coords.c_str());
191                                 break;
192                             case SkSL::Compiler::FormatArg::Kind::kCoordY:
193                                 fragBuilder->codeAppendf("%s.y", coords.c_str());
194                                 break;
195                             case SkSL::Compiler::FormatArg::Kind::kUniform:
196                                 fragBuilder->codeAppend(args.fUniformHandler->getUniformCStr(
197                                                                       fUniformHandles[arg.fIndex]));
198                                 break;
199                             case SkSL::Compiler::FormatArg::Kind::kChildProcessor:
200                                 fragBuilder->codeAppend(childNames[arg.fIndex].c_str());
201                                 break;
202                         }
203                         break;
204                     }
205                     default:
206                         fragBuilder->codeAppendf("%c", c);
207                 }
208                 substringStartIndex = i + 1;
209             }
210         }
211         fragBuilder->codeAppend(fGLSL.c_str() + substringStartIndex,
212                                 fGLSL.length() - substringStartIndex);
213     }
214 
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & _proc)215     void onSetData(const GrGLSLProgramDataManager& pdman,
216                    const GrFragmentProcessor& _proc) override {
217         size_t uniformIndex = 0;
218         size_t offset = 0;
219         const GrSkSLFP& outer = _proc.cast<GrSkSLFP>();
220         char* inputs = (char*) outer.fInputs.get();
221         for (const auto& v : outer.fFactory->fInputVars) {
222             switch (get_ctype(fContext, *v))  {
223                 case SkSL::Layout::CType::kSkPMColor: {
224                     float f1 = ((uint8_t*) inputs)[offset++] / 255.0;
225                     float f2 = ((uint8_t*) inputs)[offset++] / 255.0;
226                     float f3 = ((uint8_t*) inputs)[offset++] / 255.0;
227                     float f4 = ((uint8_t*) inputs)[offset++] / 255.0;
228                     if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
229                         pdman.set4f(fUniformHandles[uniformIndex++], f1, f2, f3, f4);
230                     }
231                     break;
232                 }
233                 case SkSL::Layout::CType::kSkPMColor4f:
234                 case SkSL::Layout::CType::kSkRect: {
235                     offset = SkAlign4(offset);
236                     float f1 = *(float*) (inputs + offset);
237                     offset += sizeof(float);
238                     float f2 = *(float*) (inputs + offset);
239                     offset += sizeof(float);
240                     float f3 = *(float*) (inputs + offset);
241                     offset += sizeof(float);
242                     float f4 = *(float*) (inputs + offset);
243                     offset += sizeof(float);
244                     if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
245                         pdman.set4f(fUniformHandles[uniformIndex++], f1, f2, f3, f4);
246                     }
247                     break;
248                 }
249                 case SkSL::Layout::CType::kInt32: {
250                     int32_t i = *(int32_t*) (inputs + offset);
251                     offset += sizeof(int32_t);
252                     if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
253                         pdman.set1i(fUniformHandles[uniformIndex++], i);
254                     }
255                     break;
256                 }
257                 case SkSL::Layout::CType::kFloat: {
258                     float f = *(float*) (inputs + offset);
259                     offset += sizeof(float);
260                     if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
261                         pdman.set1f(fUniformHandles[uniformIndex++], f);
262                     }
263                     break;
264                 }
265                 case SkSL::Layout::CType::kBool:
266                     SkASSERT(!(v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag));
267                     ++offset;
268                     break;
269                 default:
270                     SkASSERT(&v->fType == fContext.fFragmentProcessor_Type.get());
271             }
272         }
273     }
274 
275     const SkSL::Context& fContext;
276     const std::vector<const SkSL::Variable*>& fInputVars;
277     // nearly-finished GLSL; still contains printf-style "%s" format tokens
278     const SkSL::String fGLSL;
279     std::vector<SkSL::Compiler::FormatArg> fFormatArgs;
280     std::vector<UniformHandle> fUniformHandles;
281 };
282 
Make(GrContext_Base * context,int index,const char * name,const char * sksl,const void * inputs,size_t inputSize,SkSL::Program::Kind kind,const SkMatrix * matrix)283 std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext_Base* context, int index, const char* name,
284                                          const char* sksl, const void* inputs,
285                                          size_t inputSize, SkSL::Program::Kind kind,
286                                          const SkMatrix* matrix) {
287     return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(),
288                                                   context->priv().caps()->shaderCaps(),
289                                                   kind, index, name, sksl, SkString(),
290                                                   inputs, inputSize, matrix));
291 }
292 
Make(GrContext_Base * context,int index,const char * name,SkString sksl,const void * inputs,size_t inputSize,SkSL::Program::Kind kind,const SkMatrix * matrix)293 std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext_Base* context, int index, const char* name,
294                                          SkString sksl, const void* inputs, size_t inputSize,
295                                          SkSL::Program::Kind kind, const SkMatrix* matrix) {
296     return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(),
297                                                   context->priv().caps()->shaderCaps(),
298                                                   kind, index, name, nullptr, std::move(sksl),
299                                                   inputs, inputSize, matrix));
300 }
301 
GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache,const GrShaderCaps * shaderCaps,SkSL::Program::Kind kind,int index,const char * name,const char * sksl,SkString skslString,const void * inputs,size_t inputSize,const SkMatrix * matrix)302 GrSkSLFP::GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps,
303                    SkSL::Program::Kind kind, int index, const char* name, const char* sksl,
304                    SkString skslString, const void* inputs, size_t inputSize,
305                    const SkMatrix* matrix)
306         : INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
307         , fFactoryCache(factoryCache)
308         , fShaderCaps(sk_ref_sp(shaderCaps))
309         , fKind(kind)
310         , fIndex(index)
311         , fName(name)
312         , fSkSLString(skslString)
313         , fSkSL(sksl ? sksl : fSkSLString.c_str())
314         , fInputs(new int8_t[inputSize])
315         , fInputSize(inputSize) {
316     if (fInputSize) {
317         memcpy(fInputs.get(), inputs, inputSize);
318     }
319     if (matrix) {
320         fCoordTransform = GrCoordTransform(*matrix);
321         this->addCoordTransform(&fCoordTransform);
322     }
323 }
324 
GrSkSLFP(const GrSkSLFP & other)325 GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
326         : INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
327         , fFactoryCache(other.fFactoryCache)
328         , fShaderCaps(other.fShaderCaps)
329         , fFactory(other.fFactory)
330         , fKind(other.fKind)
331         , fIndex(other.fIndex)
332         , fName(other.fName)
333         , fSkSLString(other.fSkSLString)
334         , fSkSL(other.fSkSL)
335         , fInputs(new int8_t[other.fInputSize])
336         , fInputSize(other.fInputSize) {
337     if (fInputSize) {
338         memcpy(fInputs.get(), other.fInputs.get(), fInputSize);
339     }
340     if (other.numCoordTransforms()) {
341         fCoordTransform = other.fCoordTransform;
342         this->addCoordTransform(&fCoordTransform);
343     }
344 }
345 
name() const346 const char* GrSkSLFP::name() const {
347     return fName;
348 }
349 
createFactory() const350 void GrSkSLFP::createFactory() const {
351     if (!fFactory) {
352         fFactory = fFactoryCache->get(fIndex);
353         if (!fFactory) {
354             fFactory = sk_sp<GrSkSLFPFactory>(new GrSkSLFPFactory(fName, fShaderCaps.get(), fSkSL,
355                                                                   fKind));
356             fFactoryCache->set(fIndex, fFactory);
357         }
358     }
359 }
360 
addChild(std::unique_ptr<GrFragmentProcessor> child)361 void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) {
362     this->registerChildProcessor(std::move(child));
363 }
364 
onCreateGLSLInstance() const365 GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
366     this->createFactory();
367     const SkSL::Program* specialized = fFactory->getSpecialization(fKey, fInputs.get(), fInputSize);
368     SkSL::String glsl;
369     std::vector<SkSL::Compiler::FormatArg> formatArgs;
370     if (!fFactory->fCompiler.toPipelineStage(*specialized, &glsl, &formatArgs)) {
371         printf("%s\n", fFactory->fCompiler.errorText().c_str());
372         SkASSERT(false);
373     }
374     return new GrGLSLSkSLFP(specialized->fContext.get(), &fFactory->fInputVars, glsl, formatArgs);
375 }
376 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const377 void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
378                                      GrProcessorKeyBuilder* b) const {
379     this->createFactory();
380     b->add32(fIndex);
381     size_t offset = 0;
382     char* inputs = (char*) fInputs.get();
383     const SkSL::Context& context = fFactory->fCompiler.context();
384     for (const auto& v : fFactory->fInputVars) {
385         if (&v->fType == context.fFragmentProcessor_Type.get()) {
386             continue;
387         }
388         switch (get_ctype(context, *v)) {
389             case SkSL::Layout::CType::kBool:
390                 if (v->fModifiers.fLayout.fKey) {
391                     fKey += inputs[offset];
392                     b->add32(inputs[offset]);
393                 }
394                 ++offset;
395                 break;
396             case SkSL::Layout::CType::kInt32: {
397                 offset = SkAlign4(offset);
398                 if (v->fModifiers.fLayout.fKey) {
399                     fKey += inputs[offset + 0];
400                     fKey += inputs[offset + 1];
401                     fKey += inputs[offset + 2];
402                     fKey += inputs[offset + 3];
403                     b->add32(*(int32_t*) (inputs + offset));
404                 }
405                 offset += sizeof(int32_t);
406                 break;
407             }
408             case SkSL::Layout::CType::kFloat: {
409                 offset = SkAlign4(offset);
410                 if (v->fModifiers.fLayout.fKey) {
411                     fKey += inputs[offset + 0];
412                     fKey += inputs[offset + 1];
413                     fKey += inputs[offset + 2];
414                     fKey += inputs[offset + 3];
415                     b->add32(*(float*) (inputs + offset));
416                 }
417                 offset += sizeof(float);
418                 break;
419             }
420             case SkSL::Layout::CType::kSkPMColor:
421             case SkSL::Layout::CType::kSkPMColor4f:
422             case SkSL::Layout::CType::kSkRect:
423                 if (v->fModifiers.fLayout.fKey) {
424                     for (size_t i = 0; i < sizeof(float) * 4; ++i) {
425                         fKey += inputs[offset + i];
426                     }
427                     b->add32(*(int32_t*) (inputs + offset));
428                     offset += sizeof(float);
429                     b->add32(*(int32_t*) (inputs + offset));
430                     offset += sizeof(float);
431                     b->add32(*(int32_t*) (inputs + offset));
432                     offset += sizeof(float);
433                     b->add32(*(int32_t*) (inputs + offset));
434                     offset += sizeof(float);
435                 } else {
436                     offset += sizeof(float) * 4;
437                 }
438                 break;
439             default:
440                 // unsupported input var type
441                 printf("%s\n", SkSL::String(v->fType.fName).c_str());
442                 SkASSERT(false);
443         }
444     }
445 }
446 
onIsEqual(const GrFragmentProcessor & other) const447 bool GrSkSLFP::onIsEqual(const GrFragmentProcessor& other) const {
448     const GrSkSLFP& sk = other.cast<GrSkSLFP>();
449     SkASSERT(fIndex != sk.fIndex || fInputSize == sk.fInputSize);
450     return fIndex == sk.fIndex &&
451             !memcmp(fInputs.get(), sk.fInputs.get(), fInputSize);
452 }
453 
clone() const454 std::unique_ptr<GrFragmentProcessor> GrSkSLFP::clone() const {
455     std::unique_ptr<GrSkSLFP> result(new GrSkSLFP(*this));
456     for (int i = 0; i < this->numChildProcessors(); ++i) {
457         result->registerChildProcessor(this->childProcessor(i).clone());
458     }
459     return std::unique_ptr<GrFragmentProcessor>(result.release());
460 }
461 
462 // We have to do a bit of manual refcounting in the cache methods below. Ideally, we could just
463 // define fFactories to contain sk_sp<GrSkSLFPFactory> rather than GrSkSLFPFactory*, but that would
464 // require GrContext to include GrSkSLFP, which creates much bigger headaches than a few manual
465 // refcounts.
466 
get(int index)467 sk_sp<GrSkSLFPFactory> GrSkSLFPFactoryCache::get(int index) {
468     if (index >= (int) fFactories.size()) {
469         return nullptr;
470     }
471     GrSkSLFPFactory* result = fFactories[index];
472     SkSafeRef(result);
473     return sk_sp<GrSkSLFPFactory>(result);
474 }
475 
set(int index,sk_sp<GrSkSLFPFactory> factory)476 void GrSkSLFPFactoryCache::set(int index, sk_sp<GrSkSLFPFactory> factory) {
477     while (index >= (int) fFactories.size()) {
478         fFactories.emplace_back();
479     }
480     factory->ref();
481     SkASSERT(!fFactories[index]);
482     fFactories[index] = factory.get();
483 }
484 
~GrSkSLFPFactoryCache()485 GrSkSLFPFactoryCache::~GrSkSLFPFactoryCache() {
486     for (GrSkSLFPFactory* factory : fFactories) {
487         if (factory) {
488             factory->unref();
489         }
490     }
491 }
492 
493 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSkSLFP);
494 
495 #if GR_TEST_UTILS
496 
497 #include "include/effects/SkArithmeticImageFilter.h"
498 #include "include/gpu/GrContext.h"
499 #include "src/gpu/effects/generated/GrConstColorProcessor.h"
500 
501 extern const char* SKSL_ARITHMETIC_SRC;
502 extern const char* SKSL_DITHER_SRC;
503 extern const char* SKSL_OVERDRAW_SRC;
504 
505 using Value = SkSL::Program::Settings::Value;
506 
TestCreate(GrProcessorTestData * d)507 std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d) {
508     int type = d->fRandom->nextULessThan(3);
509     switch (type) {
510         case 0: {
511             static int ditherIndex = NewIndex();
512             int rangeType = d->fRandom->nextULessThan(3);
513             std::unique_ptr<GrSkSLFP> result = GrSkSLFP::Make(d->context(), ditherIndex, "Dither",
514                                                               SKSL_DITHER_SRC, &rangeType,
515                                                               sizeof(rangeType));
516             return std::unique_ptr<GrFragmentProcessor>(result.release());
517         }
518         case 1: {
519             static int arithmeticIndex = NewIndex();
520             ArithmeticFPInputs inputs;
521             inputs.k[0] = d->fRandom->nextF();
522             inputs.k[1] = d->fRandom->nextF();
523             inputs.k[2] = d->fRandom->nextF();
524             inputs.k[3] = d->fRandom->nextF();
525             inputs.enforcePMColor = d->fRandom->nextBool();
526             std::unique_ptr<GrSkSLFP> result = GrSkSLFP::Make(d->context(), arithmeticIndex,
527                                                               "Arithmetic", SKSL_ARITHMETIC_SRC,
528                                                               &inputs, sizeof(inputs));
529             result->addChild(GrConstColorProcessor::Make(
530                                                         SK_PMColor4fWHITE,
531                                                         GrConstColorProcessor::InputMode::kIgnore));
532             return std::unique_ptr<GrFragmentProcessor>(result.release());
533         }
534         case 2: {
535             static int overdrawIndex = NewIndex();
536             SkPMColor inputs[6];
537             for (int i = 0; i < 6; ++i) {
538                 inputs[i] = d->fRandom->nextU();
539             }
540             std::unique_ptr<GrSkSLFP> result = GrSkSLFP::Make(d->context(), overdrawIndex,
541                                                               "Overdraw", SKSL_OVERDRAW_SRC,
542                                                               &inputs, sizeof(inputs));
543             return std::unique_ptr<GrFragmentProcessor>(result.release());
544         }
545     }
546     SK_ABORT("unreachable");
547 }
548 
549 #endif
550