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:
John Stiles 2020-06-08 13:28:43 -04:00 committed by Skia Commit-Bot
parent d29207a24f
commit 2fbe61779a
9 changed files with 120 additions and 42 deletions

View File

@ -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);
}

View File

@ -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());
}

View File

@ -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;
}

View File

@ -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

View File

@ -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()) {

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;