aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gn/gpu.gni2
-rw-r--r--gn/sksl.gni1
-rw-r--r--src/effects/SkArithmeticImageFilter.cpp117
-rw-r--r--src/gpu/GrProcessor.h2
-rw-r--r--src/gpu/effects/GrArithmeticFP.cpp94
-rw-r--r--src/gpu/effects/GrArithmeticFP.fp20
-rw-r--r--src/gpu/effects/GrArithmeticFP.h58
-rw-r--r--src/sksl/SkSLCPPCodeGenerator.cpp56
-rw-r--r--src/sksl/SkSLCompiler.cpp3
-rw-r--r--src/sksl/SkSLContext.h2
-rw-r--r--src/sksl/SkSLHCodeGenerator.cpp55
-rw-r--r--src/sksl/SkSLHCodeGenerator.h8
-rw-r--r--src/sksl/sksl_fp.include2
-rw-r--r--tests/SkSLFPTest.cpp22
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