aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gn/gpu.gni2
-rw-r--r--gn/sksl.gni1
-rw-r--r--src/gpu/effects/GrCircleEffect.cpp88
-rw-r--r--src/gpu/effects/GrCircleEffect.fp67
-rw-r--r--src/gpu/effects/GrCircleEffect.h46
-rw-r--r--src/gpu/effects/GrOvalEffect.cpp164
6 files changed, 206 insertions, 162 deletions
diff --git a/gn/gpu.gni b/gn/gpu.gni
index e61a9074de..96056495c6 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -293,6 +293,8 @@ skia_gpu_sources = [
"$_src/gpu/effects/Gr1DKernelEffect.h",
"$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp",
"$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.h",
+ "$_src/gpu/effects/GrCircleEffect.cpp",
+ "$_src/gpu/effects/GrCircleEffect.h",
"$_src/gpu/effects/GrConfigConversionEffect.cpp",
"$_src/gpu/effects/GrConfigConversionEffect.h",
"$_src/gpu/effects/GrConstColorProcessor.cpp",
diff --git a/gn/sksl.gni b/gn/sksl.gni
index 5ddf18ffa8..c447a7bb76 100644
--- a/gn/sksl.gni
+++ b/gn/sksl.gni
@@ -26,6 +26,7 @@ skia_sksl_sources = [
skia_gpu_processor_sources = [
"$_src/effects/GrAlphaThresholdFragmentProcessor.fp",
"$_src/effects/GrCircleBlurFragmentProcessor.fp",
+ "$_src/gpu/effects/GrCircleEffect.fp",
"$_src/gpu/effects/GrDitherEffect.fp",
"$_src/gpu/effects/GrSimpleTextureEffect.fp",
]
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;