Update Gr(Circle|Ellipse)Effect to use a child FP.
We are updating FPs to receive their input via a child FP where possible, instead of relying on the input color. Change-Id: If02385558f4af3d9e5a0412975bd7d0be9c39a7f Bug: skia:10217 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/294402 Auto-Submit: John Stiles <johnstiles@google.com> Commit-Queue: John Stiles <johnstiles@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
parent
d29207a24f
commit
2fbe61779a
@ -5,6 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
in fragmentProcessor? inputFP;
|
||||
layout(key) in GrClipEdgeType edgeType;
|
||||
in float2 center;
|
||||
in float radius;
|
||||
@ -16,18 +17,23 @@ float prevRadius = -1;
|
||||
uniform float4 circle;
|
||||
|
||||
@make {
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkPoint center,
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
|
||||
GrClipEdgeType edgeType, SkPoint center,
|
||||
float radius) {
|
||||
// A radius below half causes the implicit insetting done by this processor to become
|
||||
// inverted. We could handle this case by making the processor code more complicated.
|
||||
if (radius < .5f && GrProcessorEdgeTypeIsInverseFill(edgeType)) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(edgeType, center, radius));
|
||||
return std::unique_ptr<GrFragmentProcessor>(
|
||||
new GrCircleEffect(std::move(inputFP), edgeType, center, radius));
|
||||
}
|
||||
}
|
||||
|
||||
@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
|
||||
@optimizationFlags {
|
||||
(inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
|
||||
kCompatibleWithCoverageAsAlpha_OptimizationFlag
|
||||
}
|
||||
|
||||
@setData(pdman) {
|
||||
if (radius != prevRadius || center != prevCenter) {
|
||||
@ -57,12 +63,13 @@ void main() {
|
||||
} else {
|
||||
d = half((1.0 - length((circle.xy - sk_FragCoord.xy) * circle.w)) * circle.z);
|
||||
}
|
||||
half4 inputColor = sample(inputFP, sk_InColor);
|
||||
@if (edgeType == GrClipEdgeType::kFillAA ||
|
||||
edgeType == GrClipEdgeType::kInverseFillAA ||
|
||||
edgeType == GrClipEdgeType::kHairlineAA) {
|
||||
sk_OutColor = sk_InColor * saturate(d);
|
||||
sk_OutColor = inputColor * saturate(d);
|
||||
} else {
|
||||
sk_OutColor = d > 0.5 ? sk_InColor : half4(0);
|
||||
sk_OutColor = d > 0.5 ? inputColor : half4(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,5 +82,5 @@ void main() {
|
||||
do {
|
||||
et = (GrClipEdgeType) testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
|
||||
} while (GrClipEdgeType::kHairlineAA == et);
|
||||
return GrCircleEffect::Make(et, center, radius);
|
||||
return GrCircleEffect::Make(/*inputFP=*/nullptr, et, center, radius);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "src/gpu/GrShaderCaps.h"
|
||||
}
|
||||
|
||||
in fragmentProcessor? inputFP;
|
||||
layout(key) in GrClipEdgeType edgeType;
|
||||
in float2 center;
|
||||
in float2 radii;
|
||||
@ -23,7 +24,8 @@ bool medPrecision = !sk_Caps.floatIs32Bits;
|
||||
layout(when=medPrecision) uniform float2 scale;
|
||||
|
||||
@make {
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkPoint center,
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
|
||||
GrClipEdgeType edgeType, SkPoint center,
|
||||
SkPoint radii, const GrShaderCaps& caps) {
|
||||
// Small radii produce bad results on devices without full float.
|
||||
if (!caps.floatIs32Bits() && (radii.fX < 0.5f || radii.fY < 0.5f)) {
|
||||
@ -37,11 +39,15 @@ layout(when=medPrecision) uniform float2 scale;
|
||||
if (!caps.floatIs32Bits() && (radii.fX > 16384 || radii.fY > 16384)) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(edgeType, center, radii));
|
||||
return std::unique_ptr<GrFragmentProcessor>(
|
||||
new GrEllipseEffect(std::move(inputFP), edgeType, center, radii));
|
||||
}
|
||||
}
|
||||
|
||||
@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
|
||||
@optimizationFlags {
|
||||
(inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
|
||||
kCompatibleWithCoverageAsAlpha_OptimizationFlag
|
||||
}
|
||||
|
||||
@setData(pdman) {
|
||||
if (radii != prevRadii || center != prevCenter) {
|
||||
@ -114,7 +120,8 @@ void main() {
|
||||
// hairline not supported
|
||||
discard;
|
||||
}
|
||||
sk_OutColor = sk_InColor * alpha;
|
||||
half4 inputColor = sample(inputFP, sk_InColor);
|
||||
sk_OutColor = inputColor * alpha;
|
||||
}
|
||||
|
||||
@test(testData) {
|
||||
@ -127,6 +134,6 @@ void main() {
|
||||
do {
|
||||
et = (GrClipEdgeType) testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
|
||||
} while (GrClipEdgeType::kHairlineAA == et);
|
||||
return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry),
|
||||
return GrEllipseEffect::Make(/*inputFP=*/nullptr, et, center, SkPoint::Make(rx, ry),
|
||||
*testData->caps()->shaderCaps());
|
||||
}
|
||||
|
@ -11,8 +11,9 @@
|
||||
#include "src/gpu/effects/generated/GrCircleEffect.h"
|
||||
#include "src/gpu/effects/generated/GrEllipseEffect.h"
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> GrOvalEffect::Make(GrClipEdgeType edgeType, const SkRect& oval,
|
||||
const GrShaderCaps& caps) {
|
||||
std::unique_ptr<GrFragmentProcessor> GrOvalEffect::Make(
|
||||
std::unique_ptr<GrFragmentProcessor> inputFP, GrClipEdgeType edgeType,
|
||||
const SkRect& oval, const GrShaderCaps& caps) {
|
||||
if (GrClipEdgeType::kHairlineAA == edgeType) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -20,14 +21,14 @@ std::unique_ptr<GrFragmentProcessor> GrOvalEffect::Make(GrClipEdgeType edgeType,
|
||||
SkScalar h = oval.height();
|
||||
if (SkScalarNearlyEqual(w, h)) {
|
||||
w /= 2;
|
||||
return GrCircleEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + w),
|
||||
w);
|
||||
return GrCircleEffect::Make(std::move(inputFP), edgeType,
|
||||
SkPoint::Make(oval.fLeft + w, oval.fTop + w), w);
|
||||
} else {
|
||||
w /= 2;
|
||||
h /= 2;
|
||||
return GrEllipseEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h),
|
||||
return GrEllipseEffect::Make(std::move(inputFP), edgeType,
|
||||
SkPoint::Make(oval.fLeft + w, oval.fTop + h),
|
||||
SkPoint::Make(w, h), caps);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
|
@ -21,7 +21,8 @@ namespace GrOvalEffect {
|
||||
/**
|
||||
* Creates an effect that performs clipping against an oval.
|
||||
*/
|
||||
std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRect&, const GrShaderCaps&);
|
||||
std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType,
|
||||
const SkRect&, const GrShaderCaps&);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -679,7 +679,7 @@ std::unique_ptr<GrFragmentProcessor> GrRRectEffect::Make(GrClipEdgeType edgeType
|
||||
}
|
||||
|
||||
if (rrect.isOval()) {
|
||||
return GrOvalEffect::Make(edgeType, rrect.getBounds(), caps);
|
||||
return GrOvalEffect::Make(/*inputFP=*/nullptr, edgeType, rrect.getBounds(), caps);
|
||||
}
|
||||
|
||||
if (rrect.isSimple()) {
|
||||
|
@ -35,18 +35,27 @@ public:
|
||||
fragBuilder->codeAppendf(
|
||||
"float2 prevCenter;\nfloat prevRadius = %f;\nhalf d;\n@if (%d == 2 || %d == 3) {\n "
|
||||
" d = half((length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * %s.z);\n} else {\n "
|
||||
" d = half((1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z);\n}\n@if "
|
||||
"((%d == 1 || %d == 3) || %d == 4) {\n %s = %s * clamp(d, 0.0, 1.0);\n} else "
|
||||
"{\n %s = d > 0.5 ? %s : half4(0.0);\n}\n",
|
||||
" d = half((1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z);\n}",
|
||||
prevRadius, (int)_outer.edgeType, (int)_outer.edgeType,
|
||||
args.fUniformHandler->getUniformCStr(circleVar),
|
||||
args.fUniformHandler->getUniformCStr(circleVar),
|
||||
args.fUniformHandler->getUniformCStr(circleVar),
|
||||
args.fUniformHandler->getUniformCStr(circleVar),
|
||||
args.fUniformHandler->getUniformCStr(circleVar),
|
||||
args.fUniformHandler->getUniformCStr(circleVar), (int)_outer.edgeType,
|
||||
(int)_outer.edgeType, (int)_outer.edgeType, args.fOutputColor, args.fInputColor,
|
||||
args.fOutputColor, args.fInputColor);
|
||||
args.fUniformHandler->getUniformCStr(circleVar));
|
||||
SkString _input2569 = SkStringPrintf("%s", args.fInputColor);
|
||||
SkString _sample2569;
|
||||
if (_outer.inputFP_index >= 0) {
|
||||
_sample2569 = this->invokeChild(_outer.inputFP_index, _input2569.c_str(), args);
|
||||
} else {
|
||||
_sample2569 = _input2569;
|
||||
}
|
||||
fragBuilder->codeAppendf(
|
||||
"\nhalf4 inputColor = %s;\n@if ((%d == 1 || %d == 3) || %d == 4) {\n %s = "
|
||||
"inputColor * clamp(d, 0.0, 1.0);\n} else {\n %s = d > 0.5 ? inputColor : "
|
||||
"half4(0.0);\n}\n",
|
||||
_sample2569.c_str(), (int)_outer.edgeType, (int)_outer.edgeType,
|
||||
(int)_outer.edgeType, args.fOutputColor, args.fOutputColor);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -99,9 +108,18 @@ bool GrCircleEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
}
|
||||
GrCircleEffect::GrCircleEffect(const GrCircleEffect& src)
|
||||
: INHERITED(kGrCircleEffect_ClassID, src.optimizationFlags())
|
||||
, inputFP_index(src.inputFP_index)
|
||||
, edgeType(src.edgeType)
|
||||
, center(src.center)
|
||||
, radius(src.radius) {}
|
||||
, radius(src.radius) {
|
||||
if (inputFP_index >= 0) {
|
||||
auto clone = src.childProcessor(inputFP_index).clone();
|
||||
if (src.childProcessor(inputFP_index).isSampledWithExplicitCoords()) {
|
||||
clone->setSampledWithExplicitCoords();
|
||||
}
|
||||
this->registerChildProcessor(std::move(clone));
|
||||
}
|
||||
}
|
||||
std::unique_ptr<GrFragmentProcessor> GrCircleEffect::clone() const {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(*this));
|
||||
}
|
||||
@ -116,6 +134,6 @@ std::unique_ptr<GrFragmentProcessor> GrCircleEffect::TestCreate(GrProcessorTestD
|
||||
do {
|
||||
et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
|
||||
} while (GrClipEdgeType::kHairlineAA == et);
|
||||
return GrCircleEffect::Make(et, center, radius);
|
||||
return GrCircleEffect::Make(/*inputFP=*/nullptr, et, center, radius);
|
||||
}
|
||||
#endif
|
||||
|
@ -17,7 +17,8 @@
|
||||
#include "src/gpu/GrFragmentProcessor.h"
|
||||
class GrCircleEffect : public GrFragmentProcessor {
|
||||
public:
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType,
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
|
||||
GrClipEdgeType edgeType,
|
||||
SkPoint center,
|
||||
float radius) {
|
||||
// A radius below half causes the implicit insetting done by this processor to become
|
||||
@ -25,22 +26,34 @@ public:
|
||||
if (radius < .5f && GrProcessorEdgeTypeIsInverseFill(edgeType)) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(edgeType, center, radius));
|
||||
return std::unique_ptr<GrFragmentProcessor>(
|
||||
new GrCircleEffect(std::move(inputFP), edgeType, center, radius));
|
||||
}
|
||||
GrCircleEffect(const GrCircleEffect& src);
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
||||
const char* name() const override { return "CircleEffect"; }
|
||||
int inputFP_index = -1;
|
||||
GrClipEdgeType edgeType;
|
||||
SkPoint center;
|
||||
float radius;
|
||||
|
||||
private:
|
||||
GrCircleEffect(GrClipEdgeType edgeType, SkPoint center, float radius)
|
||||
GrCircleEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
|
||||
GrClipEdgeType edgeType,
|
||||
SkPoint center,
|
||||
float radius)
|
||||
: INHERITED(kGrCircleEffect_ClassID,
|
||||
(OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag)
|
||||
(OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
|
||||
: kAll_OptimizationFlags) &
|
||||
kCompatibleWithCoverageAsAlpha_OptimizationFlag)
|
||||
, edgeType(edgeType)
|
||||
, center(center)
|
||||
, radius(radius) {}
|
||||
, radius(radius) {
|
||||
if (inputFP) {
|
||||
inputFP_index = this->numChildProcessors();
|
||||
this->registerChildProcessor(std::move(inputFP));
|
||||
}
|
||||
}
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
|
||||
bool onIsEqual(const GrFragmentProcessor&) const override;
|
||||
|
@ -56,8 +56,17 @@ public:
|
||||
" break;\n case 1:\n alpha = clamp(0.5 - half(approx_dist), 0.0, "
|
||||
"1.0);\n break;\n case 2:\n alpha = approx_dist > 0.0 ? 1.0 : "
|
||||
"0.0;\n break;\n case 3:\n alpha = clamp(0.5 + half(approx_dist), "
|
||||
"0.0, 1.0);\n break;\n default:\n discard;\n}\n%s = %s * alpha;\n",
|
||||
(int)_outer.edgeType, args.fOutputColor, args.fInputColor);
|
||||
"0.0, 1.0);\n break;\n default:\n discard;\n}",
|
||||
(int)_outer.edgeType);
|
||||
SkString _input4485 = SkStringPrintf("%s", args.fInputColor);
|
||||
SkString _sample4485;
|
||||
if (_outer.inputFP_index >= 0) {
|
||||
_sample4485 = this->invokeChild(_outer.inputFP_index, _input4485.c_str(), args);
|
||||
} else {
|
||||
_sample4485 = _input4485;
|
||||
}
|
||||
fragBuilder->codeAppendf("\nhalf4 inputColor = %s;\n%s = inputColor * alpha;\n",
|
||||
_sample4485.c_str(), args.fOutputColor);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -123,9 +132,18 @@ bool GrEllipseEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
}
|
||||
GrEllipseEffect::GrEllipseEffect(const GrEllipseEffect& src)
|
||||
: INHERITED(kGrEllipseEffect_ClassID, src.optimizationFlags())
|
||||
, inputFP_index(src.inputFP_index)
|
||||
, edgeType(src.edgeType)
|
||||
, center(src.center)
|
||||
, radii(src.radii) {}
|
||||
, radii(src.radii) {
|
||||
if (inputFP_index >= 0) {
|
||||
auto clone = src.childProcessor(inputFP_index).clone();
|
||||
if (src.childProcessor(inputFP_index).isSampledWithExplicitCoords()) {
|
||||
clone->setSampledWithExplicitCoords();
|
||||
}
|
||||
this->registerChildProcessor(std::move(clone));
|
||||
}
|
||||
}
|
||||
std::unique_ptr<GrFragmentProcessor> GrEllipseEffect::clone() const {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(*this));
|
||||
}
|
||||
@ -141,7 +159,7 @@ std::unique_ptr<GrFragmentProcessor> GrEllipseEffect::TestCreate(GrProcessorTest
|
||||
do {
|
||||
et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
|
||||
} while (GrClipEdgeType::kHairlineAA == et);
|
||||
return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry),
|
||||
return GrEllipseEffect::Make(/*inputFP=*/nullptr, et, center, SkPoint::Make(rx, ry),
|
||||
*testData->caps()->shaderCaps());
|
||||
}
|
||||
#endif
|
||||
|
@ -19,7 +19,8 @@
|
||||
#include "src/gpu/GrFragmentProcessor.h"
|
||||
class GrEllipseEffect : public GrFragmentProcessor {
|
||||
public:
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType,
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
|
||||
GrClipEdgeType edgeType,
|
||||
SkPoint center,
|
||||
SkPoint radii,
|
||||
const GrShaderCaps& caps) {
|
||||
@ -35,22 +36,34 @@ public:
|
||||
if (!caps.floatIs32Bits() && (radii.fX > 16384 || radii.fY > 16384)) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(edgeType, center, radii));
|
||||
return std::unique_ptr<GrFragmentProcessor>(
|
||||
new GrEllipseEffect(std::move(inputFP), edgeType, center, radii));
|
||||
}
|
||||
GrEllipseEffect(const GrEllipseEffect& src);
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
||||
const char* name() const override { return "EllipseEffect"; }
|
||||
int inputFP_index = -1;
|
||||
GrClipEdgeType edgeType;
|
||||
SkPoint center;
|
||||
SkPoint radii;
|
||||
|
||||
private:
|
||||
GrEllipseEffect(GrClipEdgeType edgeType, SkPoint center, SkPoint radii)
|
||||
GrEllipseEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
|
||||
GrClipEdgeType edgeType,
|
||||
SkPoint center,
|
||||
SkPoint radii)
|
||||
: INHERITED(kGrEllipseEffect_ClassID,
|
||||
(OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag)
|
||||
(OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
|
||||
: kAll_OptimizationFlags) &
|
||||
kCompatibleWithCoverageAsAlpha_OptimizationFlag)
|
||||
, edgeType(edgeType)
|
||||
, center(center)
|
||||
, radii(radii) {}
|
||||
, radii(radii) {
|
||||
if (inputFP) {
|
||||
inputFP_index = this->numChildProcessors();
|
||||
this->registerChildProcessor(std::move(inputFP));
|
||||
}
|
||||
}
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
|
||||
bool onIsEqual(const GrFragmentProcessor&) const override;
|
||||
|
Loading…
Reference in New Issue
Block a user