diff options
Diffstat (limited to 'src/gpu/effects/GrOvalEffect.cpp')
-rw-r--r-- | src/gpu/effects/GrOvalEffect.cpp | 218 |
1 files changed, 3 insertions, 215 deletions
diff --git a/src/gpu/effects/GrOvalEffect.cpp b/src/gpu/effects/GrOvalEffect.cpp index ccfc72e610..3180533146 100644 --- a/src/gpu/effects/GrOvalEffect.cpp +++ b/src/gpu/effects/GrOvalEffect.cpp @@ -8,221 +8,8 @@ #include "GrOvalEffect.h" #include "GrCircleEffect.h" -#include "GrFragmentProcessor.h" +#include "GrEllipseEffect.h" #include "SkRect.h" -#include "GrShaderCaps.h" -#include "glsl/GrGLSLFragmentProcessor.h" -#include "glsl/GrGLSLFragmentShaderBuilder.h" -#include "glsl/GrGLSLProgramDataManager.h" -#include "glsl/GrGLSLUniformHandler.h" -#include "../private/GrGLSL.h" - -////////////////////////////////////////////////////////////////////////////// - -class EllipseEffect : public GrFragmentProcessor { -public: - static sk_sp<GrFragmentProcessor> Make(GrPrimitiveEdgeType, const SkPoint& center, - SkScalar rx, SkScalar ry); - - ~EllipseEffect() override {} - - const char* name() const override { return "Ellipse"; } - - const SkPoint& getCenter() const { return fCenter; } - SkVector getRadii() const { return fRadii; } - - GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } - -private: - EllipseEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar rx, SkScalar ry); - - GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; - - void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; - - bool onIsEqual(const GrFragmentProcessor&) const override; - - SkPoint fCenter; - SkVector fRadii; - GrPrimitiveEdgeType fEdgeType; - - GR_DECLARE_FRAGMENT_PROCESSOR_TEST - - typedef GrFragmentProcessor INHERITED; -}; - -sk_sp<GrFragmentProcessor> EllipseEffect::Make(GrPrimitiveEdgeType edgeType, - const SkPoint& center, - SkScalar rx, - SkScalar ry) { - SkASSERT(rx >= 0 && ry >= 0); - return sk_sp<GrFragmentProcessor>(new EllipseEffect(edgeType, center, rx, ry)); -} - -EllipseEffect::EllipseEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar rx, - SkScalar ry) - : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag) - , fCenter(c) - , fRadii(SkVector::Make(rx, ry)) - , fEdgeType(edgeType) { - this->initClassID<EllipseEffect>(); -} - -bool EllipseEffect::onIsEqual(const GrFragmentProcessor& other) const { - const EllipseEffect& ee = other.cast<EllipseEffect>(); - return fEdgeType == ee.fEdgeType && fCenter == ee.fCenter && fRadii == ee.fRadii; -} - -////////////////////////////////////////////////////////////////////////////// - -GR_DEFINE_FRAGMENT_PROCESSOR_TEST(EllipseEffect); - -#if GR_TEST_UTILS -sk_sp<GrFragmentProcessor> EllipseEffect::TestCreate(GrProcessorTestData* d) { - SkPoint center; - center.fX = d->fRandom->nextRangeScalar(0.f, 1000.f); - center.fY = d->fRandom->nextRangeScalar(0.f, 1000.f); - SkScalar rx = d->fRandom->nextRangeF(0.f, 1000.f); - SkScalar ry = d->fRandom->nextRangeF(0.f, 1000.f); - GrPrimitiveEdgeType et; - do { - et = (GrPrimitiveEdgeType)d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt); - } while (kHairlineAA_GrProcessorEdgeType == et); - return EllipseEffect::Make(et, center, rx, ry); -} -#endif - -////////////////////////////////////////////////////////////////////////////// - -class GLEllipseEffect : public GrGLSLFragmentProcessor { -public: - GLEllipseEffect() { - fPrevRadii.fX = -1.0f; - } - - void emitCode(EmitArgs&) override; - - static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*); - -protected: - void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override; - -private: - GrGLSLProgramDataManager::UniformHandle fEllipseUniform; - GrGLSLProgramDataManager::UniformHandle fScaleUniform; - SkPoint fPrevCenter; - SkVector fPrevRadii; - - typedef GrGLSLFragmentProcessor INHERITED; -}; - -void GLEllipseEffect::emitCode(EmitArgs& args) { - const EllipseEffect& ee = args.fFp.cast<EllipseEffect>(); - const char *ellipseName; - // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2) - // The last two terms can underflow on mediump, so we use highp. - fEllipseUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, - kVec4f_GrSLType, kHigh_GrSLPrecision, - "ellipse", - &ellipseName); - // If we're on a device with a "real" mediump then we'll do the distance computation in a space - // that is normalized by the larger radius. The scale uniform will be scale, 1/scale. The - // inverse squared radii uniform values are already in this normalized space. The center is - // not. - const char* scaleName = nullptr; - if (args.fShaderCaps->floatPrecisionVaries()) { - fScaleUniform = args.fUniformHandler->addUniform( - kFragment_GrShaderFlag, kVec2f_GrSLType, kDefault_GrSLPrecision, - "scale", &scaleName); - } - - GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - - // d is the offset to the ellipse center - fragBuilder->codeAppendf("vec2 d = sk_FragCoord.xy - %s.xy;", ellipseName); - if (scaleName) { - fragBuilder->codeAppendf("d *= %s.y;", scaleName); - } - fragBuilder->codeAppendf("vec2 Z = d * %s.zw;", ellipseName); - // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1. - fragBuilder->codeAppend("float implicit = dot(Z, d) - 1.0;"); - // grad_dot is the squared length of the gradient of the implicit. - fragBuilder->codeAppendf("float grad_dot = 4.0 * dot(Z, Z);"); - // Avoid calling inversesqrt on zero. - fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); - fragBuilder->codeAppendf("float approx_dist = implicit * inversesqrt(grad_dot);"); - if (scaleName) { - fragBuilder->codeAppendf("approx_dist *= %s.x;", scaleName); - } - - switch (ee.getEdgeType()) { - case kFillAA_GrProcessorEdgeType: - fragBuilder->codeAppend("float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);"); - break; - case kInverseFillAA_GrProcessorEdgeType: - fragBuilder->codeAppend("float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);"); - break; - case kFillBW_GrProcessorEdgeType: - fragBuilder->codeAppend("float alpha = approx_dist > 0.0 ? 0.0 : 1.0;"); - break; - case kInverseFillBW_GrProcessorEdgeType: - fragBuilder->codeAppend("float alpha = approx_dist > 0.0 ? 1.0 : 0.0;"); - break; - case kHairlineAA_GrProcessorEdgeType: - SkFAIL("Hairline not expected here."); - } - - fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, args.fInputColor); -} - -void GLEllipseEffect::GenKey(const GrProcessor& effect, const GrShaderCaps&, - GrProcessorKeyBuilder* b) { - const EllipseEffect& ee = effect.cast<EllipseEffect>(); - b->add32(ee.getEdgeType()); -} - -void GLEllipseEffect::onSetData(const GrGLSLProgramDataManager& pdman, - const GrFragmentProcessor& effect) { - const EllipseEffect& ee = effect.cast<EllipseEffect>(); - if (ee.getRadii() != fPrevRadii || ee.getCenter() != fPrevCenter) { - float invRXSqd; - float invRYSqd; - // If we're using a scale factor to work around precision issues, choose the larger radius - // as the scale factor. The inv radii need to be pre-adjusted by the scale factor. - if (fScaleUniform.isValid()) { - if (ee.getRadii().fX > ee.getRadii().fY) { - invRXSqd = 1.f; - invRYSqd = (ee.getRadii().fX * ee.getRadii().fX) / - (ee.getRadii().fY * ee.getRadii().fY); - pdman.set2f(fScaleUniform, ee.getRadii().fX, 1.f / ee.getRadii().fX); - } else { - invRXSqd = (ee.getRadii().fY * ee.getRadii().fY) / - (ee.getRadii().fX * ee.getRadii().fX); - invRYSqd = 1.f; - pdman.set2f(fScaleUniform, ee.getRadii().fY, 1.f / ee.getRadii().fY); - } - } else { - invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX); - invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY); - } - pdman.set4f(fEllipseUniform, ee.getCenter().fX, ee.getCenter().fY, invRXSqd, invRYSqd); - fPrevCenter = ee.getCenter(); - fPrevRadii = ee.getRadii(); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -void EllipseEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, - GrProcessorKeyBuilder* b) const { - GLEllipseEffect::GenKey(*this, caps, b); -} - -GrGLSLFragmentProcessor* EllipseEffect::onCreateGLSLInstance() const { - return new GLEllipseEffect; -} - -////////////////////////////////////////////////////////////////////////////// sk_sp<GrFragmentProcessor> GrOvalEffect::Make(GrPrimitiveEdgeType edgeType, const SkRect& oval) { if (kHairlineAA_GrProcessorEdgeType == edgeType) { @@ -236,7 +23,8 @@ sk_sp<GrFragmentProcessor> GrOvalEffect::Make(GrPrimitiveEdgeType edgeType, cons } else { w /= 2; h /= 2; - return EllipseEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h), w, h); + return GrEllipseEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h), + SkPoint::Make(w, h)); } return nullptr; |