diff options
author | Ethan Nicholas <ethannicholas@google.com> | 2017-10-16 12:35:44 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-10-16 16:58:41 +0000 |
commit | 823994624aa5e805e16833ecd3d748fc769a164d (patch) | |
tree | 5066101c7fd3f697bf3d95b3166ad0168dc404d3 /src/effects | |
parent | d982d0579e7681ec512c0ab612f9664b7a235e79 (diff) |
converted GrRectBlurEffect to SkSL
Bug: skia:
Change-Id: I3a8e16fd2792e6fb5711815d8aad46ae30c2872e
Reviewed-on: https://skia-review.googlesource.com/59163
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src/effects')
-rw-r--r-- | src/effects/GrAlphaThresholdFragmentProcessor.cpp | 6 | ||||
-rw-r--r-- | src/effects/GrCircleBlurFragmentProcessor.cpp | 6 | ||||
-rw-r--r-- | src/effects/SkBlurMaskFilter.cpp | 248 |
3 files changed, 13 insertions, 247 deletions
diff --git a/src/effects/GrAlphaThresholdFragmentProcessor.cpp b/src/effects/GrAlphaThresholdFragmentProcessor.cpp index e1badf7f21..5ef0221be7 100644 --- a/src/effects/GrAlphaThresholdFragmentProcessor.cpp +++ b/src/effects/GrAlphaThresholdFragmentProcessor.cpp @@ -34,6 +34,12 @@ public: const GrAlphaThresholdFragmentProcessor& _outer = args.fFp.cast<GrAlphaThresholdFragmentProcessor>(); (void)_outer; + auto colorXform = _outer.colorXform(); + (void)colorXform; + auto innerThreshold = _outer.innerThreshold(); + (void)innerThreshold; + auto outerThreshold = _outer.outerThreshold(); + (void)outerThreshold; fColorSpaceHelper.emitCode(args.fUniformHandler, _outer.colorXform().get()); fInnerThresholdVar = args.fUniformHandler->addUniform( kFragment_GrShaderFlag, kHalf_GrSLType, kDefault_GrSLPrecision, "innerThreshold"); diff --git a/src/effects/GrCircleBlurFragmentProcessor.cpp b/src/effects/GrCircleBlurFragmentProcessor.cpp index 5a825f49f5..647afb8076 100644 --- a/src/effects/GrCircleBlurFragmentProcessor.cpp +++ b/src/effects/GrCircleBlurFragmentProcessor.cpp @@ -263,6 +263,12 @@ public: const GrCircleBlurFragmentProcessor& _outer = args.fFp.cast<GrCircleBlurFragmentProcessor>(); (void)_outer; + auto circleRect = _outer.circleRect(); + (void)circleRect; + auto textureRadius = _outer.textureRadius(); + (void)textureRadius; + auto solidRadius = _outer.solidRadius(); + (void)solidRadius; fCircleDataVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, kDefault_GrSLPrecision, "circleData"); fragBuilder->codeAppendf( diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index ca7de71914..7da42459f4 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -26,6 +26,7 @@ #include "GrShaderCaps.h" #include "GrStyle.h" #include "GrTextureProxy.h" +#include "effects/GrRectBlurEffect.h" #include "effects/GrSimpleTextureEffect.h" #include "effects/GrTextureDomain.h" #include "glsl/GrGLSLFragmentProcessor.h" @@ -761,253 +762,6 @@ void SkBlurMaskFilterImpl::flatten(SkWriteBuffer& buffer) const { #if SK_SUPPORT_GPU -class GrGLRectBlurEffect; - -class GrRectBlurEffect : public GrFragmentProcessor { -public: - ~GrRectBlurEffect() override { } - - const char* name() const override { return "RectBlur"; } - - static std::unique_ptr<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider, - const SkRect& rect, float sigma) { - int doubleProfileSize = SkScalarCeilToInt(12*sigma); - - if (doubleProfileSize >= rect.width() || doubleProfileSize >= rect.height()) { - // if the blur sigma is too large so the gaussian overlaps the whole - // rect in either direction, fall back to CPU path for now. - return nullptr; - } - - sk_sp<GrTextureProxy> blurProfile(CreateBlurProfileTexture(resourceProvider, sigma)); - if (!blurProfile) { - return nullptr; - } - // in OpenGL ES, mediump floats have a minimum range of 2^14. If we have coordinates bigger - // than that, the shader math will end up with infinities and result in the blur effect not - // working correctly. To avoid this, we switch into highp when the coordinates are too big. - // As 2^14 is the minimum range but the actual range can be bigger, we might end up - // switching to highp sooner than strictly necessary, but most devices that have a bigger - // range for mediump also have mediump being exactly the same as highp (e.g. all non-OpenGL - // ES devices), and thus incur no additional penalty for the switch. - static const SkScalar kMAX_BLUR_COORD = SkIntToScalar(16000); - GrSLPrecision precision; - if (SkScalarAbs(rect.top()) > kMAX_BLUR_COORD || - SkScalarAbs(rect.left()) > kMAX_BLUR_COORD || - SkScalarAbs(rect.bottom()) > kMAX_BLUR_COORD || - SkScalarAbs(rect.right()) > kMAX_BLUR_COORD || - SkScalarAbs(rect.width()) > kMAX_BLUR_COORD || - SkScalarAbs(rect.height()) > kMAX_BLUR_COORD) { - precision = kHigh_GrSLPrecision; - } else { - precision = kDefault_GrSLPrecision; - } - - return std::unique_ptr<GrFragmentProcessor>( - new GrRectBlurEffect(rect, sigma, std::move(blurProfile), precision)); - } - - std::unique_ptr<GrFragmentProcessor> clone() const override { - return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect( - fRect, fSigma, sk_ref_sp(fBlurProfileSampler.proxy()), fPrecision)); - } - - const SkRect& getRect() const { return fRect; } - float getSigma() const { return fSigma; } - GrSLPrecision precision() const { return fPrecision; } - -private: - GrRectBlurEffect(const SkRect& rect, float sigma, - sk_sp<GrTextureProxy> blurProfile, GrSLPrecision fPrecision); - - GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; - - void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; - - bool onIsEqual(const GrFragmentProcessor&) const override; - - static sk_sp<GrTextureProxy> CreateBlurProfileTexture(GrResourceProvider*, float sigma); - - SkRect fRect; - float fSigma; - TextureSampler fBlurProfileSampler; - GrSLPrecision fPrecision; - - GR_DECLARE_FRAGMENT_PROCESSOR_TEST - - typedef GrFragmentProcessor INHERITED; -}; - -class GrGLRectBlurEffect : public GrGLSLFragmentProcessor { -public: - void emitCode(EmitArgs&) override; - - static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b); - -protected: - void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override; - -private: - typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; - - UniformHandle fProxyRectUniform; - UniformHandle fProfileSizeUniform; - - typedef GrGLSLFragmentProcessor INHERITED; -}; - -void OutputRectBlurProfileLookup(GrGLSLFPFragmentBuilder* fragBuilder, - GrGLSLFragmentProcessor::SamplerHandle sampler, - const char *output, - const char *profileSize, const char *loc, - const char *blurred_width, - const char *sharp_width) { - fragBuilder->codeAppendf("half %s;", output); - fragBuilder->codeAppendf("{"); - fragBuilder->codeAppendf("half coord = ((abs(%s - 0.5 * %s) - 0.5 * %s)) / %s;", - loc, blurred_width, sharp_width, profileSize); - fragBuilder->codeAppendf("%s = ", output); - fragBuilder->appendTextureLookup(sampler, "half2(coord,0.5)"); - fragBuilder->codeAppend(".a;"); - fragBuilder->codeAppendf("}"); -} - - -void GrGLRectBlurEffect::GenKey(const GrProcessor& proc, const GrShaderCaps&, - GrProcessorKeyBuilder* b) { - const GrRectBlurEffect& rbe = proc.cast<GrRectBlurEffect>(); - - b->add32(rbe.precision()); -} - - -void GrGLRectBlurEffect::emitCode(EmitArgs& args) { - const GrRectBlurEffect& rbe = args.fFp.cast<GrRectBlurEffect>(); - - GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; - - const char *rectName; - const char *profileSizeName; - - const char* floatType = rbe.precision() == kHigh_GrSLPrecision ? "float" : "half"; - fProxyRectUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, - rbe.precision() == kHigh_GrSLPrecision ? - kFloat4_GrSLType : kHalf4_GrSLType, - "proxyRect", - &rectName); - fProfileSizeUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, - kHalf_GrSLType, - "profileSize", - &profileSizeName); - - GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - - if (args.fInputColor) { - fragBuilder->codeAppendf("half4 src=%s;", args.fInputColor); - } else { - fragBuilder->codeAppendf("half4 src=half4(1);"); - } - - fragBuilder->codeAppendf("%s2 translatedPos = sk_FragCoord.xy - %s.xy;", floatType, rectName); - fragBuilder->codeAppendf("%s width = %s.z - %s.x;", floatType, rectName, rectName); - fragBuilder->codeAppendf("%s height = %s.w - %s.y;", floatType, rectName, rectName); - - fragBuilder->codeAppendf("%s2 smallDims = half2(width - %s, height - %s);", floatType, - profileSizeName, profileSizeName); - fragBuilder->codeAppendf("%s center = 2.0 * floor(%s/2.0 + .25) - 1.0;", floatType, - profileSizeName); - fragBuilder->codeAppendf("%s2 wh = smallDims - half2(center,center);", floatType); - - OutputRectBlurProfileLookup(fragBuilder, args.fTexSamplers[0], "horiz_lookup", profileSizeName, - "translatedPos.x", "width", "wh.x"); - OutputRectBlurProfileLookup(fragBuilder, args.fTexSamplers[0], "vert_lookup", profileSizeName, - "translatedPos.y", "height", "wh.y"); - - fragBuilder->codeAppendf("half final = horiz_lookup * vert_lookup;"); - fragBuilder->codeAppendf("%s = src * final;", args.fOutputColor); -} - -void GrGLRectBlurEffect::onSetData(const GrGLSLProgramDataManager& pdman, - const GrFragmentProcessor& proc) { - const GrRectBlurEffect& rbe = proc.cast<GrRectBlurEffect>(); - SkRect rect = rbe.getRect(); - - pdman.set4f(fProxyRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); - pdman.set1f(fProfileSizeUniform, SkScalarCeilToScalar(6*rbe.getSigma())); -} - -sk_sp<GrTextureProxy> GrRectBlurEffect::CreateBlurProfileTexture( - GrResourceProvider* resourceProvider, - float sigma) { - unsigned int profileSize = SkScalarCeilToInt(6*sigma); - - static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); - GrUniqueKey key; - GrUniqueKey::Builder builder(&key, kDomain, 1); - builder[0] = profileSize; - builder.finish(); - - sk_sp<GrTextureProxy> blurProfile(resourceProvider->findOrCreateProxyByUniqueKey( - key, kTopLeft_GrSurfaceOrigin)); - if (!blurProfile) { - GrSurfaceDesc texDesc; - texDesc.fOrigin = kTopLeft_GrSurfaceOrigin; - texDesc.fWidth = profileSize; - texDesc.fHeight = 1; - texDesc.fConfig = kAlpha_8_GrPixelConfig; - - std::unique_ptr<uint8_t[]> profile(SkBlurMask::ComputeBlurProfile(sigma)); - - blurProfile = GrSurfaceProxy::MakeDeferred(resourceProvider, - texDesc, SkBudgeted::kYes, profile.get(), 0); - if (!blurProfile) { - return nullptr; - } - - SkASSERT(blurProfile->origin() == kTopLeft_GrSurfaceOrigin); - resourceProvider->assignUniqueKeyToProxy(key, blurProfile.get()); - } - - return blurProfile; -} - -GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, - sk_sp<GrTextureProxy> blurProfile, - GrSLPrecision precision) - : INHERITED(kGrRectBlurEffect_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag) - , fRect(rect) - , fSigma(sigma) - , fBlurProfileSampler(std::move(blurProfile)) - , fPrecision(precision) { - this->addTextureSampler(&fBlurProfileSampler); -} - -void GrRectBlurEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, - GrProcessorKeyBuilder* b) const { - GrGLRectBlurEffect::GenKey(*this, caps, b); -} - -GrGLSLFragmentProcessor* GrRectBlurEffect::onCreateGLSLInstance() const { - return new GrGLRectBlurEffect; -} - -bool GrRectBlurEffect::onIsEqual(const GrFragmentProcessor& sBase) const { - const GrRectBlurEffect& s = sBase.cast<GrRectBlurEffect>(); - return this->getSigma() == s.getSigma() && this->getRect() == s.getRect(); -} - -GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRectBlurEffect); - -#if GR_TEST_UTILS -std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::TestCreate(GrProcessorTestData* d) { - float sigma = d->fRandom->nextRangeF(3,8); - float width = d->fRandom->nextRangeF(200,300); - float height = d->fRandom->nextRangeF(200,300); - return GrRectBlurEffect::Make(d->resourceProvider(), - SkRect::MakeWH(width, height), sigma); -} -#endif - bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrContext* context, GrRenderTargetContext* renderTargetContext, GrPaint&& paint, |