SkSL FPs now support child processors, converted ArithmeticFP to SkSL
Bug: skia: Change-Id: I34ed3480073d05762a7d4692aeee4b87e454ce52 Reviewed-on: https://skia-review.googlesource.com/57961 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
f88c12ea20
commit
c9472af858
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
94
src/gpu/effects/GrArithmeticFP.cpp
Normal file
94
src/gpu/effects/GrArithmeticFP.cpp
Normal file
@ -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
|
20
src/gpu/effects/GrArithmeticFP.fp
Normal file
20
src/gpu/effects/GrArithmeticFP.fp
Normal file
@ -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);
|
||||
}
|
58
src/gpu/effects/GrArithmeticFP.h
Normal file
58
src/gpu/effects/GrArithmeticFP.h
Normal file
@ -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
|
@ -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",
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user