44 if (thisChild && !thisChild->isEqual(*thatChild)) {
62 for (
auto& child : fChildProcessors) {
64 child->visitTextureEffects(func);
95#if defined(GR_TEST_UTILS)
99 for (
int index = 0; index < fp.numChildProcessors(); ++index) {
100 text->appendf(
"\n%s(#%d) -> ", indent.
c_str(), index);
102 text->append(childFP->dumpInfo());
104 recursive_dump_tree_info(*childFP, indent,
text);
106 text->append(
"null");
111SkString GrFragmentProcessor::dumpTreeInfo()
const {
121 impl->fChildProcessors.push_back_n(fChildProcessors.
size());
122 for (
int i = 0; i < fChildProcessors.
size(); ++i) {
123 impl->fChildProcessors[i] = fChildProcessors[i] ? fChildProcessors[i]->makeProgramImpl()
130 return std::count_if(fChildProcessors.
begin(), fChildProcessors.
end(),
131 [](
const auto& c) { return c != nullptr; });
135bool GrFragmentProcessor::isInstantiated()
const {
157 SkASSERT(!child->fParent && !child->sampleUsage().isSampled());
163 if (child->willReadDstColor()) {
170 child->usesSampleCoords()) {
171 fFlags |= kUsesSampleCoordsIndirectly_Flag;
176 child->fParent =
this;
177 fChildProcessors.
push_back(std::move(child));
184 for (
int i = 0; i < src.numChildProcessors(); ++i) {
185 if (
auto fp = src.childProcessor(i)) {
196 "uniform half4 color;"
197 "half4 main(half4 inColor) { return color; }"
207 std::unique_ptr<GrFragmentProcessor> fp) {
211 return GrBlendFragmentProcessor::Make<SkBlendMode::kSrcIn>(
nullptr, std::move(fp));
215 std::unique_ptr<GrFragmentProcessor> child) {
218 "uniform colorFilter fp;"
219 "half4 main(half4 inColor) {"
220 "return fp.eval(inColor.rgb1) * inColor.a;"
226 "fp", std::move(child));
232 return GrBlendFragmentProcessor::Make<SkBlendMode::kModulate>(std::move(colorFP),
237 std::unique_ptr<GrFragmentProcessor> fp) {
240 "half4 main(half4 inColor) {"
241 "return saturate(inColor);"
250 std::unique_ptr<GrFragmentProcessor> fp,
const skgpu::Swizzle& swizzle) {
253 static std::unique_ptr<GrFragmentProcessor>
Make(std::unique_ptr<GrFragmentProcessor> fp,
255 return std::unique_ptr<GrFragmentProcessor>(
256 new SwizzleFragmentProcessor(std::move(fp), swizzle));
259 const char*
name()
const override {
return "Swizzle"; }
261 std::unique_ptr<GrFragmentProcessor> clone()
const override {
262 return Make(this->childProcessor(0)->clone(), fSwizzle);
266 SwizzleFragmentProcessor(std::unique_ptr<GrFragmentProcessor> fp,
268 :
INHERITED(kSwizzleFragmentProcessor_ClassID, ProcessorOptimizationFlags(fp.get()))
269 , fSwizzle(swizzle) {
270 this->registerChild(std::move(fp));
273 std::unique_ptr<ProgramImpl> onMakeProgramImpl()
const override {
276 void emitCode(EmitArgs&
args)
override {
279 const SwizzleFragmentProcessor& sfp =
args.fFp.cast<SwizzleFragmentProcessor>();
284 childColor.
c_str(), swizzle.asString().c_str());
287 return std::make_unique<Impl>();
291 b->add32(fSwizzle.asKey());
295 const SwizzleFragmentProcessor& sfp = other.
cast<SwizzleFragmentProcessor>();
296 return fSwizzle == sfp.fSwizzle;
300 return fSwizzle.applyTo(ConstantOutputForConstantInput(this->childProcessor(0), input));
314 return SwizzleFragmentProcessor::Make(std::move(fp), swizzle);
325 "uniform colorFilter fp;"
326 "uniform half4 color;"
327 "half4 main(half4 inColor) {"
328 "return fp.eval(color);"
341 std::unique_ptr<GrFragmentProcessor> fp) {
342 if (!fp || !fp->compatibleWithCoverageAsAlpha()) {
346 "half4 main(half4 inColor) { return inColor; }"
349 return GrSkSLFP::Make(effect,
"DisableCoverageAsAlpha", std::move(fp),
357 "half4 main(half4 src, half4 dst) {"
367 std::unique_ptr<GrFragmentProcessor> f, std::unique_ptr<GrFragmentProcessor> g) {
370 static std::unique_ptr<GrFragmentProcessor>
Make(std::unique_ptr<GrFragmentProcessor> f,
371 std::unique_ptr<GrFragmentProcessor> g) {
372 return std::unique_ptr<GrFragmentProcessor>(
new ComposeProcessor(std::move(f),
376 const char*
name()
const override {
return "Compose"; }
378 std::unique_ptr<GrFragmentProcessor> clone()
const override {
379 return std::unique_ptr<GrFragmentProcessor>(
new ComposeProcessor(*
this));
383 std::unique_ptr<ProgramImpl> onMakeProgramImpl()
const override {
386 void emitCode(EmitArgs&
args)
override {
389 args.fFragBuilder->codeAppendf(
"return %s;",
result.c_str());
392 return std::make_unique<Impl>();
395 ComposeProcessor(std::unique_ptr<GrFragmentProcessor> f,
396 std::unique_ptr<GrFragmentProcessor> g)
397 :
INHERITED(kSeriesFragmentProcessor_ClassID,
398 f->optimizationFlags() & g->optimizationFlags()) {
399 this->registerChild(std::move(f));
400 this->registerChild(std::move(g));
403 ComposeProcessor(
const ComposeProcessor& that) :
INHERITED(that) {}
411 color = ConstantOutputForConstantInput(this->childProcessor(1),
color);
412 color = ConstantOutputForConstantInput(this->childProcessor(0),
color);
431 std::unique_ptr<GrFragmentProcessor> series[2] = {std::move(g), std::move(f)};
435 int leadingFPsToEliminate =
info.initialProcessorsToEliminate(&knownColor);
436 switch (leadingFPsToEliminate) {
439 SkASSERT(leadingFPsToEliminate <= 2);
443 return ComposeProcessor::Make(std::move(series[1]), std::move(series[0]));
446 return ComposeProcessor::Make(std::move(series[1]),
457 std::unique_ptr<GrFragmentProcessor> child,
458 const float matrix[20],
465 "uniform int unpremulInput;"
466 "uniform int clampRGBOutput;"
467 "uniform int premulOutput;"
468 "half4 main(half4 color) {"
469 "if (bool(unpremulInput)) {"
470 "color = unpremul(color);"
472 "color = m * color + v;"
473 "if (bool(clampRGBOutput)) {"
474 "color = saturate(color);"
476 "color.a = saturate(color.a);"
478 "if (bool(premulOutput)) {"
479 "color.rgb *= color.a;"
486 SkM44 m44(matrix[ 0], matrix[ 1], matrix[ 2], matrix[ 3],
487 matrix[ 5], matrix[ 6], matrix[ 7], matrix[ 8],
488 matrix[10], matrix[11], matrix[12], matrix[13],
489 matrix[15], matrix[16], matrix[17], matrix[18]);
490 SkV4 v4 = {matrix[4], matrix[9], matrix[14], matrix[19]};
504 static std::unique_ptr<GrFragmentProcessor>
Make() {
505 return std::unique_ptr<GrFragmentProcessor>(
new SurfaceColorProcessor());
508 std::unique_ptr<GrFragmentProcessor> clone()
const override {
return Make(); }
510 const char*
name()
const override {
return "SurfaceColor"; }
513 std::unique_ptr<ProgramImpl> onMakeProgramImpl()
const override {
516 void emitCode(EmitArgs&
args)
override {
517 const char* dstColor =
args.fFragBuilder->dstColor();
518 args.fFragBuilder->codeAppendf(
"return %s;", dstColor);
521 return std::make_unique<Impl>();
524 SurfaceColorProcessor()
525 :
INHERITED(kSurfaceColorProcessor_ClassID, kNone_OptimizationFlags) {
526 this->setWillReadDstColor();
536 return SurfaceColorProcessor::Make();
542 std::unique_ptr<GrFragmentProcessor> fp) {
549 static std::unique_ptr<GrFragmentProcessor>
Make(std::unique_ptr<GrFragmentProcessor> fp) {
550 return std::unique_ptr<GrFragmentProcessor>(
new DeviceSpace(std::move(fp)));
554 DeviceSpace(std::unique_ptr<GrFragmentProcessor> fp)
560 std::unique_ptr<GrFragmentProcessor>
clone()
const override {
562 return std::unique_ptr<GrFragmentProcessor>(
new DeviceSpace(std::move(child)));
574 auto child = this->invokeChild(0,
args.fInputColor,
args,
"sk_FragCoord.xy");
575 args.fFragBuilder->codeAppendf(
"return %s;", child.c_str());
578 return std::make_unique<Impl>();
585 const char*
name()
const override {
return "DeviceSpace"; }
588 return DeviceSpace::Make(std::move(fp));
593#define CLIP_EDGE_SKSL \
594 "const int kFillBW = 0;" \
595 "const int kFillAA = 1;" \
596 "const int kInverseFillBW = 2;" \
597 "const int kInverseFillAA = 3;"
608 "uniform int edgeType;"
609 "uniform float4 rectUniform;"
611 "half4 main(float2 xy) {"
613 "if (edgeType == kFillBW || edgeType == kInverseFillBW) {"
615 "coverage = half(all(greaterThan(float4(sk_FragCoord.xy, rectUniform.zw),"
616 "float4(rectUniform.xy, sk_FragCoord.xy))));"
620 "half4 dists4 = saturate(half4(1, 1, -1, -1) *"
621 "half4(sk_FragCoord.xyxy - rectUniform));"
622 "half2 dists2 = dists4.xy + dists4.zw - 1;"
623 "coverage = dists2.x * dists2.y;"
626 "if (edgeType == kInverseFillBW || edgeType == kInverseFillAA) {"
627 "coverage = 1.0 - coverage;"
630 "return half4(coverage);"
642 "rectUniform", rectUniform);
643 return GrBlendFragmentProcessor::Make<SkBlendMode::kModulate>(std::move(rectFP),
659 "uniform int edgeType;"
662 "uniform float4 circle;"
664 "half4 main(float2 xy) {"
669 "if (edgeType == kInverseFillBW || edgeType == kInverseFillAA) {"
670 "d = half((length((circle.xy - sk_FragCoord.xy) * circle.w) - 1.0) * circle.z);"
672 "d = half((1.0 - length((circle.xy - sk_FragCoord.xy) * circle.w)) * circle.z);"
674 "return half4((edgeType == kFillAA || edgeType == kInverseFillAA)"
676 ": (d > 0.5 ? 1 : 0));"
682 effectiveRadius -= 0.5f;
684 effectiveRadius = std::max(0.001f, effectiveRadius);
686 effectiveRadius += 0.5f;
694 return GrFPSuccess(GrBlendFragmentProcessor::Make<SkBlendMode::kModulate>(std::move(inputFP),
695 std::move(circleFP)));
706 if (medPrecision && (radii.
fX < 0.5f || radii.
fY < 0.5f)) {
710 if (medPrecision && (radii.
fX > 255*radii.
fY || radii.
fY > 255*radii.
fX)) {
714 if (medPrecision && (radii.
fX > 16384 || radii.
fY > 16384)) {
720 "uniform int edgeType;"
721 "uniform int medPrecision;"
723 "uniform float4 ellipse;"
724 "uniform float2 scale;"
726 "half4 main(float2 xy) {"
728 "float2 d = sk_FragCoord.xy - ellipse.xy;"
733 "if (bool(medPrecision)) {"
736 "float2 Z = d * ellipse.zw;"
738 "float implicit = dot(Z, d) - 1;"
740 "float grad_dot = 4 * dot(Z, Z);"
742 "if (bool(medPrecision)) {"
743 "grad_dot = max(grad_dot, 6.1036e-5);"
745 "grad_dot = max(grad_dot, 1.1755e-38);"
747 "float approx_dist = implicit * inversesqrt(grad_dot);"
748 "if (bool(medPrecision)) {"
749 "approx_dist *= scale.x;"
753 "if (edgeType == kFillBW) {"
754 "alpha = approx_dist > 0.0 ? 0.0 : 1.0;"
755 "} else if (edgeType == kFillAA) {"
756 "alpha = saturate(0.5 - half(approx_dist));"
757 "} else if (edgeType == kInverseFillBW) {"
758 "alpha = approx_dist > 0.0 ? 1.0 : 0.0;"
760 "alpha = saturate(0.5 + half(approx_dist));"
762 "return half4(alpha);"
772 if (radii.
fX > radii.
fY) {
774 invRYSqd = (radii.
fX * radii.
fX) / (radii.
fY * radii.
fY);
777 invRXSqd = (radii.
fY * radii.
fY) / (radii.
fX * radii.
fX);
782 invRXSqd = 1.f / (radii.
fX * radii.
fX);
783 invRYSqd = 1.f / (radii.
fY * radii.
fY);
790 "medPrecision", GrSkSLFP::Specialize<int>(medPrecision),
793 return GrFPSuccess(GrBlendFragmentProcessor::Make<SkBlendMode::kModulate>(std::move(ellipseFP),
794 std::move(inputFP)));
800 std::unique_ptr<GrFragmentProcessor> fp) {
803 static std::unique_ptr<GrFragmentProcessor>
Make(std::unique_ptr<GrFragmentProcessor> fp) {
804 return std::unique_ptr<GrFragmentProcessor>(
805 new HighPrecisionFragmentProcessor(std::move(fp)));
808 const char*
name()
const override {
return "HighPrecision"; }
810 std::unique_ptr<GrFragmentProcessor> clone()
const override {
811 return Make(this->childProcessor(0)->clone());
815 HighPrecisionFragmentProcessor(std::unique_ptr<GrFragmentProcessor> fp)
816 :
INHERITED(kHighPrecisionFragmentProcessor_ClassID,
817 ProcessorOptimizationFlags(fp.get())) {
818 this->registerChild(std::move(fp));
821 std::unique_ptr<ProgramImpl> onMakeProgramImpl()
const override {
824 void emitCode(EmitArgs&
args)
override {
827 args.fFragBuilder->forceHighPrecision();
828 args.fFragBuilder->codeAppendf(
"return %s;", childColor.
c_str());
831 return std::make_unique<Impl>();
838 return ConstantOutputForConstantInput(this->childProcessor(0), input);
844 return HighPrecisionFragmentProcessor::Make(std::move(fp));
857 const char* inputColor,
858 const char* destColor,
860 std::string_view skslCoords) {
864 inputColor =
args.fInputColor;
878 destColor =
args.fFp.isBlendFunction() ?
args.fDestColor :
"half4(1)";
880 invocation.appendf(
", %s", destColor);
887 if (
args.fFragBuilder->getProgramBuilder()->fragmentProcessorHasCoordsParam(childProc)) {
890 if (!skslCoords.empty()) {
891 invocation.appendf(
", %.*s", (
int)skslCoords.size(), skslCoords.data());
893 invocation.appendf(
", %s",
args.fSampleCoord);
897 invocation.append(
")");
902 const char* inputColor,
903 const char* destColor,
908 inputColor =
args.fInputColor;
930 destColor =
args.fFp.isBlendFunction() ?
args.fDestColor :
"half4(1)";
932 invocation.appendf(
", %s", destColor);
943 if (
args.fFragBuilder->getProgramBuilder()->fragmentProcessorHasCoordsParam(childProc)) {
947 invocation.appendf(
", proj((%s) * %s.xy1)", matrixName.
c_str(),
args.fSampleCoord);
948 }
else if (
args.fShaderCaps->fNonsquareMatrixSupport) {
949 invocation.appendf(
", float3x2(%s) * %s.xy1", matrixName.
c_str(),
args.fSampleCoord);
951 invocation.appendf(
", ((%s) * %s.xy1).xy", matrixName.
c_str(),
args.fSampleCoord);
955 invocation.append(
")");
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static GrFPResult GrFPSuccess(std::unique_ptr< GrFragmentProcessor > fp)
std::tuple< bool, std::unique_ptr< GrFragmentProcessor > > GrFPResult
static GrFPResult GrFPFailure(std::unique_ptr< GrFragmentProcessor > fp)
std::function< void(GrSurfaceProxy *, skgpu::Mipmapped)> GrVisitProxyFunc
static constexpr bool GrClipEdgeTypeIsInverseFill(const GrClipEdgeType edgeType)
static constexpr bool GrClipEdgeTypeIsAA(const GrClipEdgeType edgeType)
static std::unique_ptr< SkEncoder > Make(SkWStream *dst, const SkPixmap *src, const SkYUVAPixmaps *srcYUVA, const SkColorSpace *srcYUVAColorSpace, const SkJpegEncoder::Options &options)
static SkV4 v4(SkV3 v, SkScalar w)
#define INHERITED(method,...)
SkRuntimeEffect * SkMakeRuntimeEffect(SkRuntimeEffect::Result(*make)(SkString, const SkRuntimeEffect::Options &), const char *sksl, SkRuntimeEffect::Options options=SkRuntimeEffect::Options{})
#define SkScalarInvert(x)
SK_API SkString static SkString SkStringPrintf()
static constexpr bool SkToBool(const T &x)
static SkScalar center(float pos0, float pos1)
SkString invokeChildWithMatrix(int childIndex, EmitArgs &parentArgs)
const char * functionName() const
void setData(const GrGLSLProgramDataManager &pdman, const GrFragmentProcessor &processor)
virtual void onSetData(const GrGLSLProgramDataManager &, const GrFragmentProcessor &)
SkString invokeChild(int childIndex, EmitArgs &parentArgs, std::string_view skslCoords={})
int numChildProcessors() const
ProgramImpl * childProcessor(int index) const
void cloneAndRegisterAllChildProcessors(const GrFragmentProcessor &src)
virtual SkPMColor4f constantOutputForConstantInput(const SkPMColor4f &) const
static std::unique_ptr< GrFragmentProcessor > SwizzleOutput(std::unique_ptr< GrFragmentProcessor >, const skgpu::Swizzle &)
void setWillReadDstColor()
static std::unique_ptr< GrFragmentProcessor > ClampOutput(std::unique_ptr< GrFragmentProcessor >)
static GrFPResult Circle(std::unique_ptr< GrFragmentProcessor >, GrClipEdgeType, SkPoint center, float radius)
virtual std::unique_ptr< GrFragmentProcessor > clone() const =0
int numNonNullChildProcessors() const
static std::unique_ptr< GrFragmentProcessor > MakeColor(SkPMColor4f color)
std::unique_ptr< ProgramImpl > makeProgramImpl() const
int numChildProcessors() const
static std::unique_ptr< GrFragmentProcessor > ModulateRGBA(std::unique_ptr< GrFragmentProcessor > child, const SkPMColor4f &color)
static std::unique_ptr< GrFragmentProcessor > DeviceSpace(std::unique_ptr< GrFragmentProcessor >)
static std::unique_ptr< GrFragmentProcessor > OverrideInput(std::unique_ptr< GrFragmentProcessor >, const SkPMColor4f &)
static std::unique_ptr< GrFragmentProcessor > SurfaceColor()
GrTextureEffect * asTextureEffect()
bool isEqual(const GrFragmentProcessor &that) const
GrFragmentProcessor * childProcessor(int index)
void visitProxies(const GrVisitProxyFunc &) const
bool isBlendFunction() const
void visitWithImpls(const std::function< void(const GrFragmentProcessor &, ProgramImpl &)> &, ProgramImpl &) const
void registerChild(std::unique_ptr< GrFragmentProcessor > child, SkSL::SampleUsage sampleUsage=SkSL::SampleUsage::PassThrough())
static std::unique_ptr< GrFragmentProcessor > Rect(std::unique_ptr< GrFragmentProcessor >, GrClipEdgeType, SkRect)
static std::unique_ptr< GrFragmentProcessor > ApplyPaintAlpha(std::unique_ptr< GrFragmentProcessor > child)
static std::unique_ptr< GrFragmentProcessor > MulInputByChildAlpha(std::unique_ptr< GrFragmentProcessor > child)
const SkSL::SampleUsage & sampleUsage() const
virtual void onAddToKey(const GrShaderCaps &, skgpu::KeyBuilder *) const =0
static std::unique_ptr< GrFragmentProcessor > HighPrecision(std::unique_ptr< GrFragmentProcessor >)
static std::unique_ptr< GrFragmentProcessor > DestColor()
static std::unique_ptr< GrFragmentProcessor > ColorMatrix(std::unique_ptr< GrFragmentProcessor > child, const float matrix[20], bool unpremulInput, bool clampRGBOutput, bool premulOutput)
static std::unique_ptr< GrFragmentProcessor > DisableCoverageAsAlpha(std::unique_ptr< GrFragmentProcessor >)
static std::unique_ptr< GrFragmentProcessor > Compose(std::unique_ptr< GrFragmentProcessor > f, std::unique_ptr< GrFragmentProcessor > g)
virtual bool onIsEqual(const GrFragmentProcessor &) const =0
static GrFPResult Ellipse(std::unique_ptr< GrFragmentProcessor >, GrClipEdgeType, SkPoint center, SkPoint radii, const GrShaderCaps &)
void visitTextureEffects(const std::function< void(const GrTextureEffect &)> &) const
virtual std::unique_ptr< ProgramImpl > onMakeProgramImpl() const =0
void codeAppendf(const char format[],...) SK_PRINTF_LIKE(2
virtual const char * name() const =0
@ kGrTextureEffect_ClassID
constexpr skgpu::Mipmapped mipmapped() const
const SkString & getName() const
@ kCompatibleWithCoverageAsAlpha
static std::unique_ptr< GrSkSLFP > Make(const SkRuntimeEffect *effect, const char *name, std::unique_ptr< GrFragmentProcessor > inputFP, OptFlags optFlags, Args &&... args)
static GrSpecializedUniform< T > Specialize(const T &value)
GrSurfaceProxy * proxy() const
const GrSurfaceProxyView & view() const
GrTexture * texture() const
GrSamplerState samplerState() const
static bool SupportsConstantOutputForConstantInput(const SkRuntimeEffect *effect)
static Result MakeForColorFilter(SkString sksl, const Options &)
static Result MakeForBlender(SkString sksl, const Options &)
static Result MakeForShader(SkString sksl, const Options &)
bool isPassThrough() const
bool isUniformMatrix() const
static const char * MatrixUniformName()
bool hasPerspective() const
static SampleUsage FragCoord()
void append(const char text[])
const char * c_str() const
static constexpr Swizzle RGBA()
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args