diff options
author | Ethan Nicholas <ethannicholas@google.com> | 2017-07-13 16:00:16 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-07-14 01:16:03 +0000 |
commit | 83d118550f7237d25e7e096cc968dbb9a06678a3 (patch) | |
tree | ed6863809baa018123e105be098009020461d720 /src/gpu/effects | |
parent | f264e996838dffd28a5a733d8d804142125944e6 (diff) |
converted CircleEffect to SkSL
Bug: skia:
Change-Id: I93d117c22ae2b374294f6a5e961c497ac2c92b09
Reviewed-on: https://skia-review.googlesource.com/23301
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Diffstat (limited to 'src/gpu/effects')
-rw-r--r-- | src/gpu/effects/GrCircleEffect.cpp | 88 | ||||
-rw-r--r-- | src/gpu/effects/GrCircleEffect.fp | 67 | ||||
-rw-r--r-- | src/gpu/effects/GrCircleEffect.h | 46 | ||||
-rw-r--r-- | src/gpu/effects/GrOvalEffect.cpp | 164 |
4 files changed, 203 insertions, 162 deletions
diff --git a/src/gpu/effects/GrCircleEffect.cpp b/src/gpu/effects/GrCircleEffect.cpp new file mode 100644 index 0000000000..acd2a9b977 --- /dev/null +++ b/src/gpu/effects/GrCircleEffect.cpp @@ -0,0 +1,88 @@ +/* + * 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 GrCircleEffect.fp; do not modify. + */ +#include "GrCircleEffect.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 GrGLSLCircleEffect : public GrGLSLFragmentProcessor { +public: + GrGLSLCircleEffect() {} + void emitCode(EmitArgs& args) override { + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; + const GrCircleEffect& _outer = args.fFp.cast<GrCircleEffect>(); + (void) _outer; +prevRadius = -1.0; + fCircleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, kDefault_GrSLPrecision, "circle"); + fragBuilder->codeAppendf("vec2 prevCenter;\nfloat prevRadius = %f;\nfloat d;\nif (%d == 2 || %d == 3) {\n d = (length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * %s.z;\n} else {\n d = (1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z;\n}\nif ((%d == 1 || %d == 3) || %d == 4) {\n d = clamp(d, 0.0, 1.0);\n} else {\n d = d > 0.5 ? 1.0 : 0.0;\n}\n%s = %s * d;\n", prevRadius, _outer.edgeType(), _outer.edgeType(), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), _outer.edgeType(), _outer.edgeType(), _outer.edgeType(), args.fOutputColor, args.fInputColor ? args.fInputColor : "vec4(1)"); + } +private: + void onSetData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& _proc) override { + const GrCircleEffect& _outer = _proc.cast<GrCircleEffect>(); + auto edgeType = _outer.edgeType(); + (void) edgeType; + auto center = _outer.center(); + (void) center; + auto radius = _outer.radius(); + (void) radius; + UniformHandle& circle = fCircleVar; + (void) circle; + + if (radius != prevRadius || center != prevCenter) { + SkScalar effectiveRadius = radius; + if (GrProcessorEdgeTypeIsInverseFill((GrPrimitiveEdgeType) edgeType)) { + effectiveRadius -= 0.5f; + } else { + effectiveRadius += 0.5f; + } + pdman.set4f(circle, center.fX, center.fY, effectiveRadius, + SkScalarInvert(effectiveRadius)); + prevCenter = center; + prevRadius = radius; + } + } +SkPoint prevCenter; +float prevRadius; + UniformHandle fCircleVar; +}; +GrGLSLFragmentProcessor* GrCircleEffect::onCreateGLSLInstance() const { + return new GrGLSLCircleEffect(); +} +void GrCircleEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const { + b->add32(fEdgeType); +} +bool GrCircleEffect::onIsEqual(const GrFragmentProcessor& other) const { + const GrCircleEffect& that = other.cast<GrCircleEffect>(); + (void) that; + if (fEdgeType != that.fEdgeType) return false; + if (fCenter != that.fCenter) return false; + if (fRadius != that.fRadius) return false; + return true; +} +GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrCircleEffect); +#if GR_TEST_UTILS +sk_sp<GrFragmentProcessor> GrCircleEffect::TestCreate(GrProcessorTestData* testData) { + + SkPoint center; + center.fX = testData->fRandom->nextRangeScalar(0.f, 1000.f); + center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f); + SkScalar radius = testData->fRandom->nextRangeF(0.f, 1000.f); + GrPrimitiveEdgeType et; + do { + et = (GrPrimitiveEdgeType) testData->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt); + } while (kHairlineAA_GrProcessorEdgeType == et); + return GrCircleEffect::Make(et, center, radius); +} +#endif +#endif diff --git a/src/gpu/effects/GrCircleEffect.fp b/src/gpu/effects/GrCircleEffect.fp new file mode 100644 index 0000000000..3f0b85017e --- /dev/null +++ b/src/gpu/effects/GrCircleEffect.fp @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +layout(key) in int edgeType; +in vec2 center; +in float radius; + +vec2 prevCenter; +float prevRadius = -1; +// The circle uniform is (center.x, center.y, radius + 0.5, 1 / (radius + 0.5)) for regular +// fills and (..., radius - 0.5, 1 / (radius - 0.5)) for inverse fills. +uniform vec4 circle; + +@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag } + +@setData(pdman) { + if (radius != prevRadius || center != prevCenter) { + SkScalar effectiveRadius = radius; + if (GrProcessorEdgeTypeIsInverseFill((GrPrimitiveEdgeType) edgeType)) { + effectiveRadius -= 0.5f; + } else { + effectiveRadius += 0.5f; + } + pdman.set4f(circle, center.fX, center.fY, effectiveRadius, + SkScalarInvert(effectiveRadius)); + prevCenter = center; + prevRadius = radius; + } +} + +void main() { + // TODO: Right now the distance to circle caclulation is performed in a space normalized to the + // radius and then denormalized. This is to prevent overflow on devices that have a "real" + // mediump. It'd be nice to only do this on mediump devices. + float d; + if (edgeType == 2 /* kInverseFillBW_GrProcessorEdgeType */ || + edgeType == 3 /* kInverseFillAA_GrProcessorEdgeType */) { + d = (length((circle.xy - sk_FragCoord.xy) * circle.w) - 1.0) * circle.z; + } else { + d = (1.0 - length((circle.xy - sk_FragCoord.xy) * circle.w)) * circle.z; + } + if (edgeType == 1 /* kFillAA_GrProcessorEdgeType */ || + edgeType == 3 /* kInverseFillAA_GrProcessorEdgeType */ || + edgeType == 4 /* kHairlineAA_GrProcessorEdgeType */) { + d = clamp(d, 0.0, 1.0); + } else { + d = d > 0.5 ? 1.0 : 0.0; + } + + sk_OutColor = sk_InColor * d; +} + +@test(testData) { + SkPoint center; + center.fX = testData->fRandom->nextRangeScalar(0.f, 1000.f); + center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f); + SkScalar radius = testData->fRandom->nextRangeF(0.f, 1000.f); + GrPrimitiveEdgeType et; + do { + et = (GrPrimitiveEdgeType) testData->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt); + } while (kHairlineAA_GrProcessorEdgeType == et); + return GrCircleEffect::Make(et, center, radius); +}
\ No newline at end of file diff --git a/src/gpu/effects/GrCircleEffect.h b/src/gpu/effects/GrCircleEffect.h new file mode 100644 index 0000000000..24a238da6c --- /dev/null +++ b/src/gpu/effects/GrCircleEffect.h @@ -0,0 +1,46 @@ +/* + * 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 GrCircleEffect.fp; do not modify. + */ +#ifndef GrCircleEffect_DEFINED +#define GrCircleEffect_DEFINED +#include "SkTypes.h" +#if SK_SUPPORT_GPU +#include "GrFragmentProcessor.h" +#include "GrCoordTransform.h" +#include "GrColorSpaceXform.h" +#include "effects/GrProxyMove.h" +class GrCircleEffect : public GrFragmentProcessor { +public: + int edgeType() const { return fEdgeType; } + SkPoint center() const { return fCenter; } + float radius() const { return fRadius; } + static sk_sp<GrFragmentProcessor> Make(int edgeType, SkPoint center, float radius) { + return sk_sp<GrFragmentProcessor>(new GrCircleEffect(edgeType, center, radius)); + } + const char* name() const override { return "CircleEffect"; } +private: + GrCircleEffect(int edgeType, SkPoint center, float radius) + : INHERITED((OptimizationFlags) kCompatibleWithCoverageAsAlpha_OptimizationFlag ) + , fEdgeType(edgeType) + , fCenter(center) + , fRadius(radius) { + this->initClassID<GrCircleEffect>(); + } + GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; + void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) const override; + bool onIsEqual(const GrFragmentProcessor&) const override; + GR_DECLARE_FRAGMENT_PROCESSOR_TEST + int fEdgeType; + SkPoint fCenter; + float fRadius; + typedef GrFragmentProcessor INHERITED; +}; +#endif +#endif diff --git a/src/gpu/effects/GrOvalEffect.cpp b/src/gpu/effects/GrOvalEffect.cpp index 20e476d255..ccfc72e610 100644 --- a/src/gpu/effects/GrOvalEffect.cpp +++ b/src/gpu/effects/GrOvalEffect.cpp @@ -7,6 +7,7 @@ #include "GrOvalEffect.h" +#include "GrCircleEffect.h" #include "GrFragmentProcessor.h" #include "SkRect.h" #include "GrShaderCaps.h" @@ -18,167 +19,6 @@ ////////////////////////////////////////////////////////////////////////////// -class CircleEffect : public GrFragmentProcessor { -public: - static sk_sp<GrFragmentProcessor> Make(GrPrimitiveEdgeType, const SkPoint& center, - SkScalar radius); - - ~CircleEffect() override {} - - const char* name() const override { return "Circle"; } - - const SkPoint& getCenter() const { return fCenter; } - SkScalar getRadius() const { return fRadius; } - - GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } - -private: - CircleEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar radius); - - GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; - - void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; - - bool onIsEqual(const GrFragmentProcessor&) const override; - - SkPoint fCenter; - SkScalar fRadius; - GrPrimitiveEdgeType fEdgeType; - - GR_DECLARE_FRAGMENT_PROCESSOR_TEST - - typedef GrFragmentProcessor INHERITED; -}; - -sk_sp<GrFragmentProcessor> CircleEffect::Make(GrPrimitiveEdgeType edgeType, const SkPoint& center, - SkScalar radius) { - SkASSERT(radius >= 0); - return sk_sp<GrFragmentProcessor>(new CircleEffect(edgeType, center, radius)); -} - -CircleEffect::CircleEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar r) - : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag) - , fCenter(c) - , fRadius(r) - , fEdgeType(edgeType) { - this->initClassID<CircleEffect>(); -} - -bool CircleEffect::onIsEqual(const GrFragmentProcessor& other) const { - const CircleEffect& ce = other.cast<CircleEffect>(); - return fEdgeType == ce.fEdgeType && fCenter == ce.fCenter && fRadius == ce.fRadius; -} - -////////////////////////////////////////////////////////////////////////////// - -GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleEffect); - -#if GR_TEST_UTILS -sk_sp<GrFragmentProcessor> CircleEffect::TestCreate(GrProcessorTestData* d) { - SkPoint center; - center.fX = d->fRandom->nextRangeScalar(0.f, 1000.f); - center.fY = d->fRandom->nextRangeScalar(0.f, 1000.f); - SkScalar radius = d->fRandom->nextRangeF(0.f, 1000.f); - GrPrimitiveEdgeType et; - do { - et = (GrPrimitiveEdgeType)d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt); - } while (kHairlineAA_GrProcessorEdgeType == et); - return CircleEffect::Make(et, center, radius); -} -#endif - -////////////////////////////////////////////////////////////////////////////// - -class GLCircleEffect : public GrGLSLFragmentProcessor { -public: - GLCircleEffect() : fPrevRadius(-1.0f) { } - - virtual void emitCode(EmitArgs&) override; - - static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*); - -protected: - void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override; - -private: - GrGLSLProgramDataManager::UniformHandle fCircleUniform; - SkPoint fPrevCenter; - SkScalar fPrevRadius; - - typedef GrGLSLFragmentProcessor INHERITED; -}; - -void GLCircleEffect::emitCode(EmitArgs& args) { - const CircleEffect& ce = args.fFp.cast<CircleEffect>(); - const char *circleName; - // The circle uniform is (center.x, center.y, radius + 0.5, 1 / (radius + 0.5)) for regular - // fills and (..., radius - 0.5, 1 / (radius - 0.5)) for inverse fills. - fCircleUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, - kVec4f_GrSLType, kDefault_GrSLPrecision, - "circle", - &circleName); - - GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - - SkASSERT(kHairlineAA_GrProcessorEdgeType != ce.getEdgeType()); - // TODO: Right now the distance to circle caclulation is performed in a space normalized to the - // radius and then denormalized. This is to prevent overflow on devices that have a "real" - // mediump. It'd be nice to only to this on mediump devices but we currently don't have the - // caps here. - if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) { - fragBuilder->codeAppendf("float d = (length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * " - "%s.z;", - circleName, circleName, circleName); - } else { - fragBuilder->codeAppendf("float d = (1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * " - "%s.z;", - circleName, circleName, circleName); - } - if (GrProcessorEdgeTypeIsAA(ce.getEdgeType())) { - fragBuilder->codeAppend("d = clamp(d, 0.0, 1.0);"); - } else { - fragBuilder->codeAppend("d = d > 0.5 ? 1.0 : 0.0;"); - } - - fragBuilder->codeAppendf("%s = %s * d;", args.fOutputColor, args.fInputColor); -} - -void GLCircleEffect::GenKey(const GrProcessor& processor, const GrShaderCaps&, - GrProcessorKeyBuilder* b) { - const CircleEffect& ce = processor.cast<CircleEffect>(); - b->add32(ce.getEdgeType()); -} - -void GLCircleEffect::onSetData(const GrGLSLProgramDataManager& pdman, - const GrFragmentProcessor& processor) { - const CircleEffect& ce = processor.cast<CircleEffect>(); - if (ce.getRadius() != fPrevRadius || ce.getCenter() != fPrevCenter) { - SkScalar radius = ce.getRadius(); - if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) { - radius -= 0.5f; - } else { - radius += 0.5f; - } - pdman.set4f(fCircleUniform, ce.getCenter().fX, ce.getCenter().fY, radius, - SkScalarInvert(radius)); - fPrevCenter = ce.getCenter(); - fPrevRadius = ce.getRadius(); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -void CircleEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, - GrProcessorKeyBuilder* b) const { - GLCircleEffect::GenKey(*this, caps, b); -} - -GrGLSLFragmentProcessor* CircleEffect::onCreateGLSLInstance() const { - return new GLCircleEffect; -} - -////////////////////////////////////////////////////////////////////////////// - class EllipseEffect : public GrFragmentProcessor { public: static sk_sp<GrFragmentProcessor> Make(GrPrimitiveEdgeType, const SkPoint& center, @@ -392,7 +232,7 @@ sk_sp<GrFragmentProcessor> GrOvalEffect::Make(GrPrimitiveEdgeType edgeType, cons SkScalar h = oval.height(); if (SkScalarNearlyEqual(w, h)) { w /= 2; - return CircleEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + w), w); + return GrCircleEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + w), w); } else { w /= 2; h /= 2; |