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.cpp",
|
||||||
"$_src/gpu/ccpr/GrCoverageCountingPathRenderer.h",
|
"$_src/gpu/ccpr/GrCoverageCountingPathRenderer.h",
|
||||||
|
|
||||||
|
"$_src/gpu/effects/GrArithmeticFP.cpp",
|
||||||
|
"$_src/gpu/effects/GrArithmeticFP.h",
|
||||||
"$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp",
|
"$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp",
|
||||||
"$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.h",
|
"$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.h",
|
||||||
"$_src/gpu/effects/GrCircleEffect.cpp",
|
"$_src/gpu/effects/GrCircleEffect.cpp",
|
||||||
|
@ -27,6 +27,7 @@ skia_sksl_sources = [
|
|||||||
skia_gpu_processor_sources = [
|
skia_gpu_processor_sources = [
|
||||||
"$_src/effects/GrAlphaThresholdFragmentProcessor.fp",
|
"$_src/effects/GrAlphaThresholdFragmentProcessor.fp",
|
||||||
"$_src/effects/GrCircleBlurFragmentProcessor.fp",
|
"$_src/effects/GrCircleBlurFragmentProcessor.fp",
|
||||||
|
"$_src/gpu/effects/GrArithmeticFP.fp",
|
||||||
"$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp",
|
"$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp",
|
||||||
"$_src/gpu/effects/GrCircleEffect.fp",
|
"$_src/gpu/effects/GrCircleEffect.fp",
|
||||||
"$_src/gpu/effects/GrConfigConversionEffect.fp",
|
"$_src/gpu/effects/GrConfigConversionEffect.fp",
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "GrRenderTargetContext.h"
|
#include "GrRenderTargetContext.h"
|
||||||
#include "GrTextureProxy.h"
|
#include "GrTextureProxy.h"
|
||||||
#include "SkGr.h"
|
#include "SkGr.h"
|
||||||
|
#include "effects/GrArithmeticFP.h"
|
||||||
#include "effects/GrConstColorProcessor.h"
|
#include "effects/GrConstColorProcessor.h"
|
||||||
#include "effects/GrTextureDomain.h"
|
#include "effects/GrTextureDomain.h"
|
||||||
#include "glsl/GrGLSLFragmentProcessor.h"
|
#include "glsl/GrGLSLFragmentProcessor.h"
|
||||||
@ -261,116 +262,8 @@ SkIRect ArithmeticImageFilterImpl::onFilterBounds(const SkIRect& src,
|
|||||||
|
|
||||||
#if SK_SUPPORT_GPU
|
#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
|
#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 k1 = d->fRandom->nextF();
|
||||||
float k2 = d->fRandom->nextF();
|
float k2 = d->fRandom->nextF();
|
||||||
float k3 = d->fRandom->nextF();
|
float k3 = d->fRandom->nextF();
|
||||||
@ -378,11 +271,11 @@ std::unique_ptr<GrFragmentProcessor> ArithmeticFP::TestCreate(GrProcessorTestDat
|
|||||||
bool enforcePMColor = d->fRandom->nextBool();
|
bool enforcePMColor = d->fRandom->nextBool();
|
||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
|
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
|
#endif
|
||||||
|
|
||||||
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ArithmeticFP);
|
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrArithmeticFP);
|
||||||
|
|
||||||
sk_sp<SkSpecialImage> ArithmeticImageFilterImpl::filterImageGPU(
|
sk_sp<SkSpecialImage> ArithmeticImageFilterImpl::filterImageGPU(
|
||||||
SkSpecialImage* source,
|
SkSpecialImage* source,
|
||||||
@ -435,7 +328,7 @@ sk_sp<SkSpecialImage> ArithmeticImageFilterImpl::filterImageGPU(
|
|||||||
paint.addColorFragmentProcessor(std::move(foregroundFP));
|
paint.addColorFragmentProcessor(std::move(foregroundFP));
|
||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> xferFP =
|
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
|
// A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed
|
||||||
if (xferFP) {
|
if (xferFP) {
|
||||||
|
@ -66,7 +66,6 @@ class GrProcessor {
|
|||||||
public:
|
public:
|
||||||
enum ClassID {
|
enum ClassID {
|
||||||
kAARectEffect_ClassID,
|
kAARectEffect_ClassID,
|
||||||
kArithmeticFP_ClassID,
|
|
||||||
kBigKeyProcessor_ClassID,
|
kBigKeyProcessor_ClassID,
|
||||||
kBlockInputFragmentProcessor_ClassID,
|
kBlockInputFragmentProcessor_ClassID,
|
||||||
kCircleGeometryProcessor_ClassID,
|
kCircleGeometryProcessor_ClassID,
|
||||||
@ -91,6 +90,7 @@ public:
|
|||||||
kFocalOutside2PtConicalEffect_ClassID,
|
kFocalOutside2PtConicalEffect_ClassID,
|
||||||
kGP_ClassID,
|
kGP_ClassID,
|
||||||
kGrAlphaThresholdFragmentProcessor_ClassID,
|
kGrAlphaThresholdFragmentProcessor_ClassID,
|
||||||
|
kGrArithmeticFP_ClassID,
|
||||||
kGrBicubicEffect_ClassID,
|
kGrBicubicEffect_ClassID,
|
||||||
kGrBitmapTextGeoProc_ClassID,
|
kGrBitmapTextGeoProc_ClassID,
|
||||||
kGrBlurredEdgeFragmentProcessor_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) {
|
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") {
|
if (c.fFunction.fBuiltin && c.fFunction.fName == "COLORSPACE") {
|
||||||
String tmpVar = "_tmpVar" + to_string(++fVarCount);
|
String tmpVar = "_tmpVar" + to_string(++fVarCount);
|
||||||
fFunctionHeader += "half4 " + tmpVar + ";";
|
fFunctionHeader += "half4 " + tmpVar + ";";
|
||||||
@ -383,8 +413,13 @@ void CPPCodeGenerator::writePrivateVars() {
|
|||||||
for (const auto& raw : decls->fVars) {
|
for (const auto& raw : decls->fVars) {
|
||||||
VarDeclaration& decl = (VarDeclaration&) *raw;
|
VarDeclaration& decl = (VarDeclaration&) *raw;
|
||||||
if (is_private(*decl.fVar)) {
|
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",
|
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());
|
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"
|
" fColorSpaceHelper.setData(%s, _outer.%s().get());\n"
|
||||||
" }\n",
|
" }\n",
|
||||||
pdman, name);
|
pdman, name);
|
||||||
|
} else if (u->fType == *fContext.fFragmentProcessor_Type) {
|
||||||
|
// do nothing
|
||||||
} else {
|
} else {
|
||||||
this->writef(" %s.set1f(%sVar, _outer.%s());\n",
|
this->writef(" %s.set1f(%sVar, _outer.%s());\n",
|
||||||
pdman, HCodeGenerator::FieldName(name).c_str(), name);
|
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"
|
this->writef(" UniformHandle& %s = %sVar;\n"
|
||||||
" (void) %s;\n",
|
" (void) %s;\n",
|
||||||
name, HCodeGenerator::FieldName(name).c_str(), name);
|
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) {
|
if (!wroteProcessor) {
|
||||||
this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName,
|
this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName,
|
||||||
fullName);
|
fullName);
|
||||||
@ -526,10 +564,13 @@ void CPPCodeGenerator::writeClone() {
|
|||||||
": INHERITED(k%s_ClassID, src.optimizationFlags())", fFullName.c_str(),
|
": INHERITED(k%s_ClassID, src.optimizationFlags())", fFullName.c_str(),
|
||||||
fFullName.c_str(), fFullName.c_str(), fFullName.c_str());
|
fFullName.c_str(), fFullName.c_str(), fFullName.c_str());
|
||||||
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
|
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
|
||||||
|
if (param->fType == *fContext.fFragmentProcessor_Type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
String fieldName = HCodeGenerator::FieldName(String(param->fName).c_str());
|
String fieldName = HCodeGenerator::FieldName(String(param->fName).c_str());
|
||||||
this->writef("\n, %s(%s)",
|
this->writef("\n, %s(src.%s)",
|
||||||
fieldName.c_str(),
|
fieldName.c_str(),
|
||||||
("src." + fieldName).c_str());
|
fieldName.c_str());
|
||||||
}
|
}
|
||||||
for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
|
for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
|
||||||
String fieldName = HCodeGenerator::FieldName(s->fArgument.c_str());
|
String fieldName = HCodeGenerator::FieldName(s->fArgument.c_str());
|
||||||
@ -537,10 +578,14 @@ void CPPCodeGenerator::writeClone() {
|
|||||||
fieldName.c_str());
|
fieldName.c_str());
|
||||||
}
|
}
|
||||||
this->writef(" {\n");
|
this->writef(" {\n");
|
||||||
|
int childCount = 0;
|
||||||
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
|
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
|
||||||
if (param->fType.kind() == Type::kSampler_Kind) {
|
if (param->fType.kind() == Type::kSampler_Kind) {
|
||||||
this->writef(" this->addTextureSampler(&%s);\n",
|
this->writef(" this->addTextureSampler(&%s);\n",
|
||||||
HCodeGenerator::FieldName(String(param->fName).c_str()).c_str());
|
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)) {
|
for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
|
||||||
@ -687,6 +732,9 @@ bool CPPCodeGenerator::generateCode() {
|
|||||||
" (void) that;\n",
|
" (void) that;\n",
|
||||||
fullName, fullName, fullName);
|
fullName, fullName, fullName);
|
||||||
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
|
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
|
||||||
|
if (param->fType == *fContext.fFragmentProcessor_Type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
String nameString(param->fName);
|
String nameString(param->fName);
|
||||||
const char* name = nameString.c_str();
|
const char* name = nameString.c_str();
|
||||||
this->writef(" if (%s != that.%s) return false;\n",
|
this->writef(" if (%s != that.%s) return false;\n",
|
||||||
|
@ -185,6 +185,7 @@ Compiler::Compiler(Flags flags)
|
|||||||
ADD_TYPE(GSampler2DArrayShadow);
|
ADD_TYPE(GSampler2DArrayShadow);
|
||||||
ADD_TYPE(GSamplerCubeArrayShadow);
|
ADD_TYPE(GSamplerCubeArrayShadow);
|
||||||
ADD_TYPE(ColorSpaceXform);
|
ADD_TYPE(ColorSpaceXform);
|
||||||
|
ADD_TYPE(FragmentProcessor);
|
||||||
|
|
||||||
StringFragment skCapsName("sk_Caps");
|
StringFragment skCapsName("sk_Caps");
|
||||||
Variable* skCaps = new Variable(-1, Modifiers(), skCapsName,
|
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) {
|
bool Compiler::toH(const Program& program, String name, OutputStream& out) {
|
||||||
fSource = program.fSource.get();
|
fSource = program.fSource.get();
|
||||||
HCodeGenerator cg(&program, this, name, &out);
|
HCodeGenerator cg(&fContext, &program, this, name, &out);
|
||||||
bool result = cg.generateCode();
|
bool result = cg.generateCode();
|
||||||
fSource = nullptr;
|
fSource = nullptr;
|
||||||
this->writeErrorCount();
|
this->writeErrorCount();
|
||||||
|
@ -185,6 +185,7 @@ public:
|
|||||||
, fSkCaps_Type(new Type("$sk_Caps"))
|
, fSkCaps_Type(new Type("$sk_Caps"))
|
||||||
, fSkArgs_Type(new Type("$sk_Args"))
|
, fSkArgs_Type(new Type("$sk_Args"))
|
||||||
, fColorSpaceXform_Type(new Type("colorSpaceXform", *fFloat_Type, 4, 4))
|
, fColorSpaceXform_Type(new Type("colorSpaceXform", *fFloat_Type, 4, 4))
|
||||||
|
, fFragmentProcessor_Type(new Type("fragmentProcessor"))
|
||||||
, fDefined_Expression(new Defined(*fInvalid_Type)) {}
|
, fDefined_Expression(new Defined(*fInvalid_Type)) {}
|
||||||
|
|
||||||
static std::vector<const Type*> static_type(const Type& t) {
|
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> fSkCaps_Type;
|
||||||
const std::unique_ptr<Type> fSkArgs_Type;
|
const std::unique_ptr<Type> fSkArgs_Type;
|
||||||
const std::unique_ptr<Type> fColorSpaceXform_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
|
// 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
|
// could have several different values, or the analyzer is otherwise unable to assign it a
|
||||||
|
@ -15,37 +15,45 @@
|
|||||||
|
|
||||||
namespace SkSL {
|
namespace SkSL {
|
||||||
|
|
||||||
HCodeGenerator::HCodeGenerator(const Program* program, ErrorReporter* errors, String name,
|
HCodeGenerator::HCodeGenerator(const Context* context, const Program* program,
|
||||||
OutputStream* out)
|
ErrorReporter* errors, String name, OutputStream* out)
|
||||||
: INHERITED(program, errors, out)
|
: INHERITED(program, errors, out)
|
||||||
|
, fContext(*context)
|
||||||
, fName(std::move(name))
|
, fName(std::move(name))
|
||||||
, fFullName(String::printf("Gr%s", fName.c_str()))
|
, fFullName(String::printf("Gr%s", fName.c_str()))
|
||||||
, fSectionAndParameterHelper(*program, *errors) {}
|
, fSectionAndParameterHelper(*program, *errors) {}
|
||||||
|
|
||||||
String HCodeGenerator::ParameterType(const Type& type) {
|
String HCodeGenerator::ParameterType(const Context& context, const Type& type) {
|
||||||
if (type.name() == "float" || type.name() == "half") {
|
if (type == *context.fFloat_Type || type == *context.fHalf_Type) {
|
||||||
return "float";
|
return "float";
|
||||||
} else if (type.name() == "float2" || type.name() == "half2") {
|
} else if (type == *context.fFloat2_Type || type == *context.fHalf2_Type) {
|
||||||
return "SkPoint";
|
return "SkPoint";
|
||||||
} else if (type.name() == "int4" || type.name() == "short4") {
|
} else if (type == *context.fInt4_Type || type == *context.fShort4_Type) {
|
||||||
return "SkIRect";
|
return "SkIRect";
|
||||||
} else if (type.name() == "float4" || type.name() == "half4") {
|
} else if (type == *context.fFloat4_Type || type == *context.fHalf4_Type) {
|
||||||
return "SkRect";
|
return "SkRect";
|
||||||
} else if (type.name() == "float4x4" || type.name() == "half4x4") {
|
} else if (type == *context.fFloat4x4_Type || type == *context.fHalf4x4_Type) {
|
||||||
return "SkMatrix44";
|
return "SkMatrix44";
|
||||||
} else if (type.kind() == Type::kSampler_Kind) {
|
} else if (type.kind() == Type::kSampler_Kind) {
|
||||||
return "sk_sp<GrTextureProxy>";
|
return "sk_sp<GrTextureProxy>";
|
||||||
} else if (type.name() == "colorSpaceXform") {
|
} else if (type == *context.fColorSpaceXform_Type) {
|
||||||
return "sk_sp<GrColorSpaceXform>";
|
return "sk_sp<GrColorSpaceXform>";
|
||||||
|
} else if (type == *context.fFragmentProcessor_Type) {
|
||||||
|
return "std::unique_ptr<GrFragmentProcessor>";
|
||||||
}
|
}
|
||||||
return type.name();
|
return type.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
String HCodeGenerator::FieldType(const Type& type) {
|
String HCodeGenerator::FieldType(const Context& context, const Type& type) {
|
||||||
if (type.kind() == Type::kSampler_Kind) {
|
if (type.kind() == Type::kSampler_Kind) {
|
||||||
return "TextureSampler";
|
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) {
|
void HCodeGenerator::writef(const char* s, va_list va) {
|
||||||
@ -128,7 +136,7 @@ void HCodeGenerator::writeMake() {
|
|||||||
this->writef(" static std::unique_ptr<GrFragmentProcessor> Make(");
|
this->writef(" static std::unique_ptr<GrFragmentProcessor> Make(");
|
||||||
separator = "";
|
separator = "";
|
||||||
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
|
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());
|
String(param->fName).c_str());
|
||||||
separator = ", ";
|
separator = ", ";
|
||||||
}
|
}
|
||||||
@ -138,7 +146,11 @@ void HCodeGenerator::writeMake() {
|
|||||||
fFullName.c_str());
|
fFullName.c_str());
|
||||||
separator = "";
|
separator = "";
|
||||||
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
|
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 = ", ";
|
separator = ", ";
|
||||||
}
|
}
|
||||||
this->writeExtraConstructorParams(separator);
|
this->writeExtraConstructorParams(separator);
|
||||||
@ -166,7 +178,7 @@ void HCodeGenerator::writeConstructor() {
|
|||||||
this->writef(" %s(", fFullName.c_str());
|
this->writef(" %s(", fFullName.c_str());
|
||||||
const char* separator = "";
|
const char* separator = "";
|
||||||
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
|
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());
|
String(param->fName).c_str());
|
||||||
separator = ", ";
|
separator = ", ";
|
||||||
}
|
}
|
||||||
@ -190,6 +202,8 @@ void HCodeGenerator::writeConstructor() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->writef(")");
|
this->writef(")");
|
||||||
|
} else if (param->fType == *fContext.fFragmentProcessor_Type) {
|
||||||
|
// do nothing
|
||||||
} else {
|
} else {
|
||||||
this->writef("\n , %s(%s)", FieldName(name).c_str(), name);
|
this->writef("\n , %s(%s)", FieldName(name).c_str(), name);
|
||||||
}
|
}
|
||||||
@ -205,6 +219,9 @@ void HCodeGenerator::writeConstructor() {
|
|||||||
if (param->fType.kind() == Type::kSampler_Kind) {
|
if (param->fType.kind() == Type::kSampler_Kind) {
|
||||||
this->writef(" this->addTextureSampler(&%s);\n",
|
this->writef(" this->addTextureSampler(&%s);\n",
|
||||||
FieldName(String(param->fName).c_str()).c_str());
|
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)) {
|
for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
|
||||||
@ -217,7 +234,10 @@ void HCodeGenerator::writeConstructor() {
|
|||||||
void HCodeGenerator::writeFields() {
|
void HCodeGenerator::writeFields() {
|
||||||
this->writeSection(FIELDS_SECTION);
|
this->writeSection(FIELDS_SECTION);
|
||||||
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
|
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());
|
FieldName(String(param->fName).c_str()).c_str());
|
||||||
}
|
}
|
||||||
for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
|
for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
|
||||||
@ -243,13 +263,14 @@ bool HCodeGenerator::generateCode() {
|
|||||||
fFullName.c_str());
|
fFullName.c_str());
|
||||||
this->writeSection(CLASS_SECTION);
|
this->writeSection(CLASS_SECTION);
|
||||||
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
String nameString(param->fName);
|
String nameString(param->fName);
|
||||||
const char* name = nameString.c_str();
|
const char* name = nameString.c_str();
|
||||||
this->writef(" %s %s() const { return %s; }\n",
|
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->writeMake();
|
||||||
this->writef(" %s(const %s& src);\n"
|
this->writef(" %s(const %s& src);\n"
|
||||||
|
@ -32,13 +32,14 @@ namespace SkSL {
|
|||||||
|
|
||||||
class HCodeGenerator : public CodeGenerator {
|
class HCodeGenerator : public CodeGenerator {
|
||||||
public:
|
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;
|
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) {
|
static String FieldName(const char* varName) {
|
||||||
return String::printf("f%c%s", toupper(varName[0]), varName + 1);
|
return String::printf("f%c%s", toupper(varName[0]), varName + 1);
|
||||||
@ -63,6 +64,7 @@ private:
|
|||||||
|
|
||||||
void failOnSection(const char* section, const char* msg);
|
void failOnSection(const char* section, const char* msg);
|
||||||
|
|
||||||
|
const Context& fContext;
|
||||||
String fName;
|
String fName;
|
||||||
String fFullName;
|
String fFullName;
|
||||||
SectionAndParameterHelper fSectionAndParameterHelper;
|
SectionAndParameterHelper fSectionAndParameterHelper;
|
||||||
|
@ -22,4 +22,6 @@ layout(builtin=10005) float2[] sk_TransformedCoords2D;
|
|||||||
layout(builtin=10006) sampler2D[] sk_TextureSamplers;
|
layout(builtin=10006) sampler2D[] sk_TextureSamplers;
|
||||||
|
|
||||||
half4 COLORSPACE(half4 color, colorSpaceXform colorSpace);
|
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
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user