diff options
-rw-r--r-- | gn/gpu.gni | 2 | ||||
-rw-r--r-- | gn/sksl.gni | 1 | ||||
-rw-r--r-- | src/effects/SkArithmeticImageFilter.cpp | 117 | ||||
-rw-r--r-- | src/gpu/GrProcessor.h | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrArithmeticFP.cpp | 94 | ||||
-rw-r--r-- | src/gpu/effects/GrArithmeticFP.fp | 20 | ||||
-rw-r--r-- | src/gpu/effects/GrArithmeticFP.h | 58 | ||||
-rw-r--r-- | src/sksl/SkSLCPPCodeGenerator.cpp | 56 | ||||
-rw-r--r-- | src/sksl/SkSLCompiler.cpp | 3 | ||||
-rw-r--r-- | src/sksl/SkSLContext.h | 2 | ||||
-rw-r--r-- | src/sksl/SkSLHCodeGenerator.cpp | 55 | ||||
-rw-r--r-- | src/sksl/SkSLHCodeGenerator.h | 8 | ||||
-rw-r--r-- | src/sksl/sksl_fp.include | 2 | ||||
-rw-r--r-- | tests/SkSLFPTest.cpp | 22 |
14 files changed, 304 insertions, 138 deletions
diff --git a/gn/gpu.gni b/gn/gpu.gni index b026e824fb..ef751dba4c 100644 --- a/gn/gpu.gni +++ b/gn/gpu.gni @@ -310,6 +310,8 @@ skia_gpu_sources = [ "$_src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp", "$_src/gpu/ccpr/GrCoverageCountingPathRenderer.h", + "$_src/gpu/effects/GrArithmeticFP.cpp", + "$_src/gpu/effects/GrArithmeticFP.h", "$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp", "$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.h", "$_src/gpu/effects/GrCircleEffect.cpp", diff --git a/gn/sksl.gni b/gn/sksl.gni index 55e8bd270b..1de85f6fae 100644 --- a/gn/sksl.gni +++ b/gn/sksl.gni @@ -27,6 +27,7 @@ skia_sksl_sources = [ skia_gpu_processor_sources = [ "$_src/effects/GrAlphaThresholdFragmentProcessor.fp", "$_src/effects/GrCircleBlurFragmentProcessor.fp", + "$_src/gpu/effects/GrArithmeticFP.fp", "$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp", "$_src/gpu/effects/GrCircleEffect.fp", "$_src/gpu/effects/GrConfigConversionEffect.fp", diff --git a/src/effects/SkArithmeticImageFilter.cpp b/src/effects/SkArithmeticImageFilter.cpp index 27bf28e54b..d2dd17c91a 100644 --- a/src/effects/SkArithmeticImageFilter.cpp +++ b/src/effects/SkArithmeticImageFilter.cpp @@ -20,6 +20,7 @@ #include "GrRenderTargetContext.h" #include "GrTextureProxy.h" #include "SkGr.h" +#include "effects/GrArithmeticFP.h" #include "effects/GrConstColorProcessor.h" #include "effects/GrTextureDomain.h" #include "glsl/GrGLSLFragmentProcessor.h" @@ -261,116 +262,8 @@ SkIRect ArithmeticImageFilterImpl::onFilterBounds(const SkIRect& src, #if SK_SUPPORT_GPU -namespace { -class ArithmeticFP : public GrFragmentProcessor { -public: - static std::unique_ptr<GrFragmentProcessor> Make(float k1, float k2, float k3, float k4, - bool enforcePMColor, - std::unique_ptr<GrFragmentProcessor> dst) { - return std::unique_ptr<GrFragmentProcessor>( - new ArithmeticFP(k1, k2, k3, k4, enforcePMColor, std::move(dst))); - } - - ~ArithmeticFP() override {} - - const char* name() const override { return "Arithmetic"; } - - SkString dumpInfo() const override { - SkString str; - str.appendf("K1: %.2f K2: %.2f K3: %.2f K4: %.2f", fK1, fK2, fK3, fK4); - return str; - } - - std::unique_ptr<GrFragmentProcessor> clone() const override { - return Make(fK1, fK2, fK3, fK4, fEnforcePMColor, this->childProcessor(0).clone()); - } - - float k1() const { return fK1; } - float k2() const { return fK2; } - float k3() const { return fK3; } - float k4() const { return fK4; } - bool enforcePMColor() const { return fEnforcePMColor; } - -private: - GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { - class GLSLFP : public GrGLSLFragmentProcessor { - public: - void emitCode(EmitArgs& args) override { - const ArithmeticFP& arith = args.fFp.cast<ArithmeticFP>(); - - GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - SkString dstColor("dstColor"); - this->emitChild(0, &dstColor, args); - - fKUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, - "k"); - const char* kUni = args.fUniformHandler->getUniformCStr(fKUni); - - // We don't try to optimize for this case at all - if (!args.fInputColor) { - fragBuilder->codeAppend("const half4 src = half4(1);"); - } else { - fragBuilder->codeAppendf("half4 src = %s;", args.fInputColor); - } - - fragBuilder->codeAppendf("half4 dst = %s;", dstColor.c_str()); - fragBuilder->codeAppendf("%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;", - args.fOutputColor, kUni, kUni, kUni, kUni); - fragBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);\n", args.fOutputColor, - args.fOutputColor); - if (arith.fEnforcePMColor) { - fragBuilder->codeAppendf("%s.rgb = min(%s.rgb, %s.a);", args.fOutputColor, - args.fOutputColor, args.fOutputColor); - } - } - - protected: - void onSetData(const GrGLSLProgramDataManager& pdman, - const GrFragmentProcessor& proc) override { - const ArithmeticFP& arith = proc.cast<ArithmeticFP>(); - pdman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4()); - } - - private: - GrGLSLProgramDataManager::UniformHandle fKUni; - }; - return new GLSLFP; - } - - void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override { - b->add32(fEnforcePMColor ? 1 : 0); - } - - bool onIsEqual(const GrFragmentProcessor& fpBase) const override { - const ArithmeticFP& fp = fpBase.cast<ArithmeticFP>(); - return fK1 == fp.fK1 && fK2 == fp.fK2 && fK3 == fp.fK3 && fK4 == fp.fK4 && - fEnforcePMColor == fp.fEnforcePMColor; - } - - // This could implement the const input -> const output optimization but it's unlikely to help. - ArithmeticFP(float k1, float k2, float k3, float k4, bool enforcePMColor, - std::unique_ptr<GrFragmentProcessor> dst) - : INHERITED(kArithmeticFP_ClassID, kNone_OptimizationFlags) - , fK1(k1) - , fK2(k2) - , fK3(k3) - , fK4(k4) - , fEnforcePMColor(enforcePMColor) { - SkASSERT(dst); - SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(dst)); - SkASSERT(0 == dstIndex); - } - - float fK1, fK2, fK3, fK4; - bool fEnforcePMColor; - - GR_DECLARE_FRAGMENT_PROCESSOR_TEST - typedef GrFragmentProcessor INHERITED; -}; -} - #if GR_TEST_UTILS -std::unique_ptr<GrFragmentProcessor> ArithmeticFP::TestCreate(GrProcessorTestData* d) { +std::unique_ptr<GrFragmentProcessor> GrArithmeticFP::TestCreate(GrProcessorTestData* d) { float k1 = d->fRandom->nextF(); float k2 = d->fRandom->nextF(); float k3 = d->fRandom->nextF(); @@ -378,11 +271,11 @@ std::unique_ptr<GrFragmentProcessor> ArithmeticFP::TestCreate(GrProcessorTestDat bool enforcePMColor = d->fRandom->nextBool(); std::unique_ptr<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d)); - return ArithmeticFP::Make(k1, k2, k3, k4, enforcePMColor, std::move(dst)); + return GrArithmeticFP::Make(k1, k2, k3, k4, enforcePMColor, std::move(dst)); } #endif -GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ArithmeticFP); +GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrArithmeticFP); sk_sp<SkSpecialImage> ArithmeticImageFilterImpl::filterImageGPU( SkSpecialImage* source, @@ -435,7 +328,7 @@ sk_sp<SkSpecialImage> ArithmeticImageFilterImpl::filterImageGPU( paint.addColorFragmentProcessor(std::move(foregroundFP)); std::unique_ptr<GrFragmentProcessor> xferFP = - ArithmeticFP::Make(fK[0], fK[1], fK[2], fK[3], fEnforcePMColor, std::move(bgFP)); + GrArithmeticFP::Make(fK[0], fK[1], fK[2], fK[3], fEnforcePMColor, std::move(bgFP)); // A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed if (xferFP) { diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h index 7f513169f8..77a6808430 100644 --- a/src/gpu/GrProcessor.h +++ b/src/gpu/GrProcessor.h @@ -66,7 +66,6 @@ class GrProcessor { public: enum ClassID { kAARectEffect_ClassID, - kArithmeticFP_ClassID, kBigKeyProcessor_ClassID, kBlockInputFragmentProcessor_ClassID, kCircleGeometryProcessor_ClassID, @@ -91,6 +90,7 @@ public: kFocalOutside2PtConicalEffect_ClassID, kGP_ClassID, kGrAlphaThresholdFragmentProcessor_ClassID, + kGrArithmeticFP_ClassID, kGrBicubicEffect_ClassID, kGrBitmapTextGeoProc_ClassID, kGrBlurredEdgeFragmentProcessor_ClassID, diff --git a/src/gpu/effects/GrArithmeticFP.cpp b/src/gpu/effects/GrArithmeticFP.cpp new file mode 100644 index 0000000000..bc73b45dc2 --- /dev/null +++ b/src/gpu/effects/GrArithmeticFP.cpp @@ -0,0 +1,94 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * This file was autogenerated from GrArithmeticFP.fp; do not modify. + */ +#include "GrArithmeticFP.h" +#if SK_SUPPORT_GPU +#include "glsl/GrGLSLColorSpaceXformHelper.h" +#include "glsl/GrGLSLFragmentProcessor.h" +#include "glsl/GrGLSLFragmentShaderBuilder.h" +#include "glsl/GrGLSLProgramBuilder.h" +#include "SkSLCPP.h" +#include "SkSLUtil.h" +class GrGLSLArithmeticFP : public GrGLSLFragmentProcessor { +public: + GrGLSLArithmeticFP() {} + void emitCode(EmitArgs& args) override { + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; + const GrArithmeticFP& _outer = args.fFp.cast<GrArithmeticFP>(); + (void)_outer; + fKVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType, + kDefault_GrSLPrecision, "k"); + SkString _child0("_child0"); + this->emitChild(0, &_child0, args); + fragBuilder->codeAppendf( + "half4 dst = %s;\n%s = half4(clamp(float4(float4(((%s.x * float4(%s)) * dst + %s.y " + "* float4(%s)) + %s.z * float4(dst)) + %s.w), 0.0, 1.0));\nif (%s) {\n %s.xyz = " + "half3(min(float3(%s.xyz), float(%s.w)));\n}\n", + _child0.c_str(), args.fOutputColor, args.fUniformHandler->getUniformCStr(fKVar), + args.fInputColor ? args.fInputColor : "half4(1)", + args.fUniformHandler->getUniformCStr(fKVar), + args.fInputColor ? args.fInputColor : "half4(1)", + args.fUniformHandler->getUniformCStr(fKVar), + args.fUniformHandler->getUniformCStr(fKVar), + (_outer.enforcePMColor() ? "true" : "false"), args.fOutputColor, args.fOutputColor, + args.fOutputColor); + } + +private: + void onSetData(const GrGLSLProgramDataManager& pdman, + const GrFragmentProcessor& _proc) override { + const GrArithmeticFP& _outer = _proc.cast<GrArithmeticFP>(); + auto k1 = _outer.k1(); + (void)k1; + auto k2 = _outer.k2(); + (void)k2; + auto k3 = _outer.k3(); + (void)k3; + auto k4 = _outer.k4(); + (void)k4; + auto enforcePMColor = _outer.enforcePMColor(); + (void)enforcePMColor; + UniformHandle& k = fKVar; + (void)k; + + pdman.set4f(k, k1, k2, k3, k4); + } + UniformHandle fKVar; +}; +GrGLSLFragmentProcessor* GrArithmeticFP::onCreateGLSLInstance() const { + return new GrGLSLArithmeticFP(); +} +void GrArithmeticFP::onGetGLSLProcessorKey(const GrShaderCaps& caps, + GrProcessorKeyBuilder* b) const { + b->add32(fEnforcePMColor); +} +bool GrArithmeticFP::onIsEqual(const GrFragmentProcessor& other) const { + const GrArithmeticFP& that = other.cast<GrArithmeticFP>(); + (void)that; + if (fK1 != that.fK1) return false; + if (fK2 != that.fK2) return false; + if (fK3 != that.fK3) return false; + if (fK4 != that.fK4) return false; + if (fEnforcePMColor != that.fEnforcePMColor) return false; + return true; +} +GrArithmeticFP::GrArithmeticFP(const GrArithmeticFP& src) + : INHERITED(kGrArithmeticFP_ClassID, src.optimizationFlags()) + , fK1(src.fK1) + , fK2(src.fK2) + , fK3(src.fK3) + , fK4(src.fK4) + , fEnforcePMColor(src.fEnforcePMColor) { + this->registerChildProcessor(src.childProcessor(0).clone()); +} +std::unique_ptr<GrFragmentProcessor> GrArithmeticFP::clone() const { + return std::unique_ptr<GrFragmentProcessor>(new GrArithmeticFP(*this)); +} +#endif diff --git a/src/gpu/effects/GrArithmeticFP.fp b/src/gpu/effects/GrArithmeticFP.fp new file mode 100644 index 0000000000..546fa79843 --- /dev/null +++ b/src/gpu/effects/GrArithmeticFP.fp @@ -0,0 +1,20 @@ +in float k1; +in float k2; +in float k3; +in float k4; +layout(key) in bool enforcePMColor; +in fragmentProcessor child; + +uniform float4 k; + +void main() { + half4 dst = process(child); + sk_OutColor = clamp(k.x * sk_InColor * dst + k.y * sk_InColor + k.z * dst + k.w, 0, 1); + if (enforcePMColor) { + sk_OutColor.rgb = min(sk_OutColor.rgb, sk_OutColor.a); + } +} + +@setData(pdman) { + pdman.set4f(k, k1, k2, k3, k4); +} diff --git a/src/gpu/effects/GrArithmeticFP.h b/src/gpu/effects/GrArithmeticFP.h new file mode 100644 index 0000000000..ee151a1fa6 --- /dev/null +++ b/src/gpu/effects/GrArithmeticFP.h @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * This file was autogenerated from GrArithmeticFP.fp; do not modify. + */ +#ifndef GrArithmeticFP_DEFINED +#define GrArithmeticFP_DEFINED +#include "SkTypes.h" +#if SK_SUPPORT_GPU +#include "GrFragmentProcessor.h" +#include "GrCoordTransform.h" +#include "GrColorSpaceXform.h" +class GrArithmeticFP : public GrFragmentProcessor { +public: + float k1() const { return fK1; } + float k2() const { return fK2; } + float k3() const { return fK3; } + float k4() const { return fK4; } + bool enforcePMColor() const { return fEnforcePMColor; } + static std::unique_ptr<GrFragmentProcessor> Make(float k1, float k2, float k3, float k4, + bool enforcePMColor, + std::unique_ptr<GrFragmentProcessor> child) { + return std::unique_ptr<GrFragmentProcessor>( + new GrArithmeticFP(k1, k2, k3, k4, enforcePMColor, child->clone())); + } + GrArithmeticFP(const GrArithmeticFP& src); + std::unique_ptr<GrFragmentProcessor> clone() const override; + const char* name() const override { return "ArithmeticFP"; } + +private: + GrArithmeticFP(float k1, float k2, float k3, float k4, bool enforcePMColor, + std::unique_ptr<GrFragmentProcessor> child) + : INHERITED(kGrArithmeticFP_ClassID, kNone_OptimizationFlags) + , fK1(k1) + , fK2(k2) + , fK3(k3) + , fK4(k4) + , fEnforcePMColor(enforcePMColor) { + this->registerChildProcessor(std::move(child)); + } + GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; + void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; + bool onIsEqual(const GrFragmentProcessor&) const override; + GR_DECLARE_FRAGMENT_PROCESSOR_TEST + float fK1; + float fK2; + float fK3; + float fK4; + bool fEnforcePMColor; + typedef GrFragmentProcessor INHERITED; +}; +#endif +#endif diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp index 30661301dc..705155eb5b 100644 --- a/src/sksl/SkSLCPPCodeGenerator.cpp +++ b/src/sksl/SkSLCPPCodeGenerator.cpp @@ -246,6 +246,36 @@ void CPPCodeGenerator::writeSwitchStatement(const SwitchStatement& s) { } void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) { + if (c.fFunction.fBuiltin && c.fFunction.fName == "process") { + ASSERT(c.fArguments.size() == 1); + ASSERT(Expression::kVariableReference_Kind == c.fArguments[0]->fKind); + int index = 0; + bool found = false; + for (const auto& p : fProgram.fElements) { + if (ProgramElement::kVar_Kind == p->fKind) { + const VarDeclarations* decls = (const VarDeclarations*) p.get(); + for (const auto& raw : decls->fVars) { + VarDeclaration& decl = (VarDeclaration&) *raw; + if (decl.fVar == &((VariableReference&) *c.fArguments[0]).fVariable) { + found = true; + } else if (decl.fVar->fType == *fContext.fFragmentProcessor_Type) { + ++index; + } + } + } + if (found) { + break; + } + } + ASSERT(found); + String childName = "_child" + to_string(index); + fExtraEmitCodeCode += " SkString " + childName + "(\"" + childName + "\");\n" + + " this->emitChild(" + to_string(index) + ", &" + childName + + ", args);\n"; + this->write("%s"); + fFormatArgs.push_back(childName + ".c_str()"); + return; + } if (c.fFunction.fBuiltin && c.fFunction.fName == "COLORSPACE") { String tmpVar = "_tmpVar" + to_string(++fVarCount); fFunctionHeader += "half4 " + tmpVar + ";"; @@ -383,8 +413,13 @@ void CPPCodeGenerator::writePrivateVars() { for (const auto& raw : decls->fVars) { VarDeclaration& decl = (VarDeclaration&) *raw; if (is_private(*decl.fVar)) { + if (decl.fVar->fType == *fContext.fFragmentProcessor_Type) { + fErrors.error(decl.fOffset, + "fragmentProcessor variables must be declared 'in'"); + return; + } this->writef("%s %s;\n", - HCodeGenerator::FieldType(decl.fVar->fType).c_str(), + HCodeGenerator::FieldType(fContext, decl.fVar->fType).c_str(), String(decl.fVar->fName).c_str()); } } @@ -477,6 +512,8 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) { " fColorSpaceHelper.setData(%s, _outer.%s().get());\n" " }\n", pdman, name); + } else if (u->fType == *fContext.fFragmentProcessor_Type) { + // do nothing } else { this->writef(" %s.set1f(%sVar, _outer.%s());\n", pdman, HCodeGenerator::FieldName(name).c_str(), name); @@ -498,7 +535,8 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) { this->writef(" UniformHandle& %s = %sVar;\n" " (void) %s;\n", name, HCodeGenerator::FieldName(name).c_str(), name); - } else if (SectionAndParameterHelper::IsParameter(*decl.fVar)) { + } else if (SectionAndParameterHelper::IsParameter(*decl.fVar) && + decl.fVar->fType != *fContext.fFragmentProcessor_Type) { if (!wroteProcessor) { this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName, fullName); @@ -526,10 +564,13 @@ void CPPCodeGenerator::writeClone() { ": INHERITED(k%s_ClassID, src.optimizationFlags())", fFullName.c_str(), fFullName.c_str(), fFullName.c_str(), fFullName.c_str()); for (const auto& param : fSectionAndParameterHelper.getParameters()) { + if (param->fType == *fContext.fFragmentProcessor_Type) { + continue; + } String fieldName = HCodeGenerator::FieldName(String(param->fName).c_str()); - this->writef("\n, %s(%s)", + this->writef("\n, %s(src.%s)", fieldName.c_str(), - ("src." + fieldName).c_str()); + fieldName.c_str()); } for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) { String fieldName = HCodeGenerator::FieldName(s->fArgument.c_str()); @@ -537,10 +578,14 @@ void CPPCodeGenerator::writeClone() { fieldName.c_str()); } this->writef(" {\n"); + int childCount = 0; for (const auto& param : fSectionAndParameterHelper.getParameters()) { if (param->fType.kind() == Type::kSampler_Kind) { this->writef(" this->addTextureSampler(&%s);\n", HCodeGenerator::FieldName(String(param->fName).c_str()).c_str()); + } else if (param->fType == *fContext.fFragmentProcessor_Type) { + this->writef(" this->registerChildProcessor(src.childProcessor(%d).clone());" + "\n", childCount++); } } for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) { @@ -687,6 +732,9 @@ bool CPPCodeGenerator::generateCode() { " (void) that;\n", fullName, fullName, fullName); for (const auto& param : fSectionAndParameterHelper.getParameters()) { + if (param->fType == *fContext.fFragmentProcessor_Type) { + continue; + } String nameString(param->fName); const char* name = nameString.c_str(); this->writef(" if (%s != that.%s) return false;\n", diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp index 5373f9d5a2..23c09ac1c1 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -185,6 +185,7 @@ Compiler::Compiler(Flags flags) ADD_TYPE(GSampler2DArrayShadow); ADD_TYPE(GSamplerCubeArrayShadow); ADD_TYPE(ColorSpaceXform); + ADD_TYPE(FragmentProcessor); StringFragment skCapsName("sk_Caps"); Variable* skCaps = new Variable(-1, Modifiers(), skCapsName, @@ -1246,7 +1247,7 @@ bool Compiler::toCPP(const Program& program, String name, OutputStream& out) { bool Compiler::toH(const Program& program, String name, OutputStream& out) { fSource = program.fSource.get(); - HCodeGenerator cg(&program, this, name, &out); + HCodeGenerator cg(&fContext, &program, this, name, &out); bool result = cg.generateCode(); fSource = nullptr; this->writeErrorCount(); diff --git a/src/sksl/SkSLContext.h b/src/sksl/SkSLContext.h index 5061b61fd3..a8158be4a0 100644 --- a/src/sksl/SkSLContext.h +++ b/src/sksl/SkSLContext.h @@ -185,6 +185,7 @@ public: , fSkCaps_Type(new Type("$sk_Caps")) , fSkArgs_Type(new Type("$sk_Args")) , fColorSpaceXform_Type(new Type("colorSpaceXform", *fFloat_Type, 4, 4)) + , fFragmentProcessor_Type(new Type("fragmentProcessor")) , fDefined_Expression(new Defined(*fInvalid_Type)) {} static std::vector<const Type*> static_type(const Type& t) { @@ -333,6 +334,7 @@ public: const std::unique_ptr<Type> fSkCaps_Type; const std::unique_ptr<Type> fSkArgs_Type; const std::unique_ptr<Type> fColorSpaceXform_Type; + const std::unique_ptr<Type> fFragmentProcessor_Type; // dummy expression used to mark that a variable has a value during dataflow analysis (when it // could have several different values, or the analyzer is otherwise unable to assign it a diff --git a/src/sksl/SkSLHCodeGenerator.cpp b/src/sksl/SkSLHCodeGenerator.cpp index eb8263187f..a4a5c9a6ac 100644 --- a/src/sksl/SkSLHCodeGenerator.cpp +++ b/src/sksl/SkSLHCodeGenerator.cpp @@ -15,37 +15,45 @@ namespace SkSL { -HCodeGenerator::HCodeGenerator(const Program* program, ErrorReporter* errors, String name, - OutputStream* out) +HCodeGenerator::HCodeGenerator(const Context* context, const Program* program, + ErrorReporter* errors, String name, OutputStream* out) : INHERITED(program, errors, out) +, fContext(*context) , fName(std::move(name)) , fFullName(String::printf("Gr%s", fName.c_str())) , fSectionAndParameterHelper(*program, *errors) {} -String HCodeGenerator::ParameterType(const Type& type) { - if (type.name() == "float" || type.name() == "half") { +String HCodeGenerator::ParameterType(const Context& context, const Type& type) { + if (type == *context.fFloat_Type || type == *context.fHalf_Type) { return "float"; - } else if (type.name() == "float2" || type.name() == "half2") { + } else if (type == *context.fFloat2_Type || type == *context.fHalf2_Type) { return "SkPoint"; - } else if (type.name() == "int4" || type.name() == "short4") { + } else if (type == *context.fInt4_Type || type == *context.fShort4_Type) { return "SkIRect"; - } else if (type.name() == "float4" || type.name() == "half4") { + } else if (type == *context.fFloat4_Type || type == *context.fHalf4_Type) { return "SkRect"; - } else if (type.name() == "float4x4" || type.name() == "half4x4") { + } else if (type == *context.fFloat4x4_Type || type == *context.fHalf4x4_Type) { return "SkMatrix44"; } else if (type.kind() == Type::kSampler_Kind) { return "sk_sp<GrTextureProxy>"; - } else if (type.name() == "colorSpaceXform") { + } else if (type == *context.fColorSpaceXform_Type) { return "sk_sp<GrColorSpaceXform>"; + } else if (type == *context.fFragmentProcessor_Type) { + return "std::unique_ptr<GrFragmentProcessor>"; } return type.name(); } -String HCodeGenerator::FieldType(const Type& type) { +String HCodeGenerator::FieldType(const Context& context, const Type& type) { if (type.kind() == Type::kSampler_Kind) { return "TextureSampler"; + } else if (type == *context.fFragmentProcessor_Type) { + // we don't store fragment processors in fields, they get registered via + // registerChildProcessor instead + ASSERT(false); + return "<error>"; } - return ParameterType(type); + return ParameterType(context, type); } void HCodeGenerator::writef(const char* s, va_list va) { @@ -128,7 +136,7 @@ void HCodeGenerator::writeMake() { this->writef(" static std::unique_ptr<GrFragmentProcessor> Make("); separator = ""; for (const auto& param : fSectionAndParameterHelper.getParameters()) { - this->writef("%s%s %s", separator, ParameterType(param->fType).c_str(), + this->writef("%s%s %s", separator, ParameterType(fContext, param->fType).c_str(), String(param->fName).c_str()); separator = ", "; } @@ -138,7 +146,11 @@ void HCodeGenerator::writeMake() { fFullName.c_str()); separator = ""; for (const auto& param : fSectionAndParameterHelper.getParameters()) { - this->writef("%s%s", separator, String(param->fName).c_str()); + if (param->fType == *fContext.fFragmentProcessor_Type) { + this->writef("%s%s->clone()", separator, String(param->fName).c_str()); + } else { + this->writef("%s%s", separator, String(param->fName).c_str()); + } separator = ", "; } this->writeExtraConstructorParams(separator); @@ -166,7 +178,7 @@ void HCodeGenerator::writeConstructor() { this->writef(" %s(", fFullName.c_str()); const char* separator = ""; for (const auto& param : fSectionAndParameterHelper.getParameters()) { - this->writef("%s%s %s", separator, ParameterType(param->fType).c_str(), + this->writef("%s%s %s", separator, ParameterType(fContext, param->fType).c_str(), String(param->fName).c_str()); separator = ", "; } @@ -190,6 +202,8 @@ void HCodeGenerator::writeConstructor() { } } this->writef(")"); + } else if (param->fType == *fContext.fFragmentProcessor_Type) { + // do nothing } else { this->writef("\n , %s(%s)", FieldName(name).c_str(), name); } @@ -205,6 +219,9 @@ void HCodeGenerator::writeConstructor() { if (param->fType.kind() == Type::kSampler_Kind) { this->writef(" this->addTextureSampler(&%s);\n", FieldName(String(param->fName).c_str()).c_str()); + } else if (param->fType == *fContext.fFragmentProcessor_Type) { + this->writef(" this->registerChildProcessor(std::move(%s));", + String(param->fName).c_str()); } } for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) { @@ -217,7 +234,10 @@ void HCodeGenerator::writeConstructor() { void HCodeGenerator::writeFields() { this->writeSection(FIELDS_SECTION); for (const auto& param : fSectionAndParameterHelper.getParameters()) { - this->writef(" %s %s;\n", FieldType(param->fType).c_str(), + if (param->fType == *fContext.fFragmentProcessor_Type) { + continue; + } + this->writef(" %s %s;\n", FieldType(fContext, param->fType).c_str(), FieldName(String(param->fName).c_str()).c_str()); } for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) { @@ -243,13 +263,14 @@ bool HCodeGenerator::generateCode() { fFullName.c_str()); this->writeSection(CLASS_SECTION); for (const auto& param : fSectionAndParameterHelper.getParameters()) { - if (param->fType.kind() == Type::kSampler_Kind) { + if (param->fType.kind() == Type::kSampler_Kind || + param->fType.kind() == Type::kOther_Kind) { continue; } String nameString(param->fName); const char* name = nameString.c_str(); this->writef(" %s %s() const { return %s; }\n", - FieldType(param->fType).c_str(), name, FieldName(name).c_str()); + FieldType(fContext, param->fType).c_str(), name, FieldName(name).c_str()); } this->writeMake(); this->writef(" %s(const %s& src);\n" diff --git a/src/sksl/SkSLHCodeGenerator.h b/src/sksl/SkSLHCodeGenerator.h index 3e76555136..5d3b0e7100 100644 --- a/src/sksl/SkSLHCodeGenerator.h +++ b/src/sksl/SkSLHCodeGenerator.h @@ -32,13 +32,14 @@ namespace SkSL { class HCodeGenerator : public CodeGenerator { public: - HCodeGenerator(const Program* program, ErrorReporter* errors, String name, OutputStream* out); + HCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors, + String name, OutputStream* out); bool generateCode() override; - static String ParameterType(const Type& type); + static String ParameterType(const Context& context, const Type& type); - static String FieldType(const Type& type); + static String FieldType(const Context& context, const Type& type); static String FieldName(const char* varName) { return String::printf("f%c%s", toupper(varName[0]), varName + 1); @@ -63,6 +64,7 @@ private: void failOnSection(const char* section, const char* msg); + const Context& fContext; String fName; String fFullName; SectionAndParameterHelper fSectionAndParameterHelper; diff --git a/src/sksl/sksl_fp.include b/src/sksl/sksl_fp.include index 2cb46f1302..eacc7e802e 100644 --- a/src/sksl/sksl_fp.include +++ b/src/sksl/sksl_fp.include @@ -22,4 +22,6 @@ layout(builtin=10005) float2[] sk_TransformedCoords2D; layout(builtin=10006) sampler2D[] sk_TextureSamplers; half4 COLORSPACE(half4 color, colorSpaceXform colorSpace); + +half4 process(fragmentProcessor fp); ) diff --git a/tests/SkSLFPTest.cpp b/tests/SkSLFPTest.cpp index 3e95d9975f..ce09b952a7 100644 --- a/tests/SkSLFPTest.cpp +++ b/tests/SkSLFPTest.cpp @@ -402,4 +402,26 @@ DEF_TEST(SkSLFPLayoutWhen, r) { } +DEF_TEST(SkSLFPChildProcessors, r) { + test(r, + "in fragmentProcessor child1;" + "in fragmentProcessor child2;" + "void main() {" + " sk_OutColor = process(child1) * process(child2);" + "}", + *SkSL::ShaderCapsFactory::Default(), + { + "this->registerChildProcessor(std::move(child1));", + "this->registerChildProcessor(std::move(child2));" + }, + { + "SkString _child0(\"_child0\");", + "this->emitChild(0, &_child0, args);", + "SkString _child1(\"_child1\");", + "this->emitChild(1, &_child1, args);", + "this->registerChildProcessor(src.childProcessor(0).clone());", + "this->registerChildProcessor(src.childProcessor(1).clone());" + }); +} + #endif |