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/gpu/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/gpu/effects')
-rw-r--r-- | src/gpu/effects/GrArithmeticFP.cpp | 10 | ||||
-rw-r--r-- | src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrCircleEffect.cpp | 6 | ||||
-rw-r--r-- | src/gpu/effects/GrConfigConversionEffect.cpp | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrDitherEffect.cpp | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrEllipseEffect.cpp | 6 | ||||
-rw-r--r-- | src/gpu/effects/GrRectBlurEffect.cpp | 167 | ||||
-rw-r--r-- | src/gpu/effects/GrRectBlurEffect.fp | 123 | ||||
-rw-r--r-- | src/gpu/effects/GrRectBlurEffect.h | 100 | ||||
-rw-r--r-- | src/gpu/effects/GrSimpleTextureEffect.cpp | 4 |
10 files changed, 422 insertions, 0 deletions
diff --git a/src/gpu/effects/GrArithmeticFP.cpp b/src/gpu/effects/GrArithmeticFP.cpp index bc73b45dc2..fec3fbffad 100644 --- a/src/gpu/effects/GrArithmeticFP.cpp +++ b/src/gpu/effects/GrArithmeticFP.cpp @@ -23,6 +23,16 @@ public: GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; const GrArithmeticFP& _outer = args.fFp.cast<GrArithmeticFP>(); (void)_outer; + auto k1 = _outer.k1(); + (void)k1; + auto k2 = _outer.k2(); + (void)k2; + auto k3 = _outer.k3(); + (void)k3; + auto k4 = _outer.k4(); + (void)k4; + auto enforcePMColor = _outer.enforcePMColor(); + (void)enforcePMColor; fKVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType, kDefault_GrSLPrecision, "k"); SkString _child0("_child0"); diff --git a/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp b/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp index 551adeac8f..2e42b238ab 100644 --- a/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp +++ b/src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp @@ -24,6 +24,8 @@ public: const GrBlurredEdgeFragmentProcessor& _outer = args.fFp.cast<GrBlurredEdgeFragmentProcessor>(); (void)_outer; + auto mode = _outer.mode(); + (void)mode; fragBuilder->codeAppendf( "half factor = half(1.0 - float(%s.w));\n@switch (%d) {\n case 0:\n " "factor = half(exp(float(float(-factor * factor) * 4.0)) - " diff --git a/src/gpu/effects/GrCircleEffect.cpp b/src/gpu/effects/GrCircleEffect.cpp index 3c0e11b621..b181669d4d 100644 --- a/src/gpu/effects/GrCircleEffect.cpp +++ b/src/gpu/effects/GrCircleEffect.cpp @@ -23,6 +23,12 @@ public: GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; const GrCircleEffect& _outer = args.fFp.cast<GrCircleEffect>(); (void)_outer; + auto edgeType = _outer.edgeType(); + (void)edgeType; + auto center = _outer.center(); + (void)center; + auto radius = _outer.radius(); + (void)radius; prevRadius = -1.0; fCircleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, kDefault_GrSLPrecision, "circle"); diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp index 0d2a139816..d8c9044bbb 100644 --- a/src/gpu/effects/GrConfigConversionEffect.cpp +++ b/src/gpu/effects/GrConfigConversionEffect.cpp @@ -23,6 +23,8 @@ public: GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; const GrConfigConversionEffect& _outer = args.fFp.cast<GrConfigConversionEffect>(); (void)_outer; + auto pmConversion = _outer.pmConversion(); + (void)pmConversion; fragBuilder->forceHighPrecision(); fragBuilder->codeAppendf( diff --git a/src/gpu/effects/GrDitherEffect.cpp b/src/gpu/effects/GrDitherEffect.cpp index 2498ffc134..88b8bdba9d 100644 --- a/src/gpu/effects/GrDitherEffect.cpp +++ b/src/gpu/effects/GrDitherEffect.cpp @@ -23,6 +23,8 @@ public: GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; const GrDitherEffect& _outer = args.fFp.cast<GrDitherEffect>(); (void)_outer; + auto rangeType = _outer.rangeType(); + (void)rangeType; fragBuilder->codeAppendf( "half value;\nhalf range;\n@switch (%d) {\n case 0:\n range = " "0.0039215686274509803;\n break;\n case 1:\n range = " diff --git a/src/gpu/effects/GrEllipseEffect.cpp b/src/gpu/effects/GrEllipseEffect.cpp index 8621c9a242..61b8f96c07 100644 --- a/src/gpu/effects/GrEllipseEffect.cpp +++ b/src/gpu/effects/GrEllipseEffect.cpp @@ -23,6 +23,12 @@ public: GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; const GrEllipseEffect& _outer = args.fFp.cast<GrEllipseEffect>(); (void)_outer; + auto edgeType = _outer.edgeType(); + (void)edgeType; + auto center = _outer.center(); + (void)center; + auto radii = _outer.radii(); + (void)radii; prevRadii = half2(-1.0); useScale = sk_Caps.floatPrecisionVaries; fEllipseVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType, diff --git a/src/gpu/effects/GrRectBlurEffect.cpp b/src/gpu/effects/GrRectBlurEffect.cpp new file mode 100644 index 0000000000..3b2d8a1927 --- /dev/null +++ b/src/gpu/effects/GrRectBlurEffect.cpp @@ -0,0 +1,167 @@ +/* + * 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 GrRectBlurEffect.fp; do not modify. + */ +#include "GrRectBlurEffect.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 GrGLSLRectBlurEffect : public GrGLSLFragmentProcessor { +public: + GrGLSLRectBlurEffect() {} + void emitCode(EmitArgs& args) override { + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; + const GrRectBlurEffect& _outer = args.fFp.cast<GrRectBlurEffect>(); + (void)_outer; + auto rect = _outer.rect(); + (void)rect; + auto sigma = _outer.sigma(); + (void)sigma; + highPrecision = ((((abs(rect.left()) > 16000.0 || abs(rect.top()) > 16000.0) || + abs(rect.right()) > 16000.0) || + abs(rect.bottom()) > 16000.0) || + abs(rect.right() - rect.left()) > 16000.0) || + abs(rect.bottom() - rect.top()) > 16000.0; + fRectVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType, + kDefault_GrSLPrecision, "rect"); + if (!highPrecision) { + fProxyRectHalfVar = + args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, + kDefault_GrSLPrecision, "proxyRectHalf"); + } + if (highPrecision) { + fProxyRectFloatVar = + args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType, + kDefault_GrSLPrecision, "proxyRectFloat"); + } + fProfileSizeVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, + kDefault_GrSLPrecision, "profileSize"); + fragBuilder->codeAppendf( + "bool highPrecision = %s;\n@if (highPrecision) {\n float2 translatedPos = " + "sk_FragCoord.xy - %s.xy;\n float width = %s.z - %s.x;\n float height = %s.w " + "- %s.y;\n float2 smallDims = float2(width - float(%s), height - float(%s));\n " + " float center = 2.0 * floor(float(float(%s / 2.0) + 0.25)) - 1.0;\n float2 wh " + "= smallDims - float2(center, center);\n half hcoord = " + "half((abs(translatedPos.x - 0.5 * width) - 0.5 * wh.x) / float(%s));\n half " + "hlookup = texture(%s, float2(float(hcoord), 0.5)).%s.w", + (highPrecision ? "true" : "false"), args.fUniformHandler->getUniformCStr(fRectVar), + args.fUniformHandler->getUniformCStr(fRectVar), + args.fUniformHandler->getUniformCStr(fRectVar), + args.fUniformHandler->getUniformCStr(fRectVar), + args.fUniformHandler->getUniformCStr(fRectVar), + args.fUniformHandler->getUniformCStr(fProfileSizeVar), + args.fUniformHandler->getUniformCStr(fProfileSizeVar), + args.fUniformHandler->getUniformCStr(fProfileSizeVar), + args.fUniformHandler->getUniformCStr(fProfileSizeVar), + fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(), + fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str()); + fragBuilder->codeAppendf( + ";\n half vcoord = half((abs(translatedPos.y - 0.5 * height) - 0.5 * wh.y) / " + "float(%s));\n half vlookup = texture(%s, float2(float(vcoord), 0.5)).%s.w;\n " + " %s = (%s * hlookup) * vlookup;\n} else {\n half2 translatedPos = " + "half2(sk_FragCoord.xy - %s.xy);\n half width = half(%s.z - %s.x);\n half " + "height = half(%s.w - %s.y);\n half2 smallDims = half2(width - %s, height - " + "%s);\n half center = half(2.0 * floor(float(float(%s / 2.0) + 0.25)) - 1.0);\n " + " half2 wh = smallDims - half2(float2(floa", + args.fUniformHandler->getUniformCStr(fProfileSizeVar), + fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(), + fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(), + args.fOutputColor, args.fInputColor ? args.fInputColor : "half4(1)", + args.fUniformHandler->getUniformCStr(fRectVar), + args.fUniformHandler->getUniformCStr(fRectVar), + args.fUniformHandler->getUniformCStr(fRectVar), + args.fUniformHandler->getUniformCStr(fRectVar), + args.fUniformHandler->getUniformCStr(fRectVar), + args.fUniformHandler->getUniformCStr(fProfileSizeVar), + args.fUniformHandler->getUniformCStr(fProfileSizeVar), + args.fUniformHandler->getUniformCStr(fProfileSizeVar)); + fragBuilder->codeAppendf( + "t(center), float(center)));\n half hcoord = " + "half((abs(float(float(translatedPos.x) - 0.5 * float(width))) - 0.5 * " + "float(wh.x)) / float(%s));\n half hlookup = texture(%s, float2(float(hcoord), " + "0.5)).%s.w;\n half vcoord = half((abs(float(float(translatedPos.y) - 0.5 * " + "float(height))) - 0.5 * float(wh.y)) / float(%s));\n half vlookup = " + "texture(%s, float2(float(vcoord), 0.5)).%s.w;\n %s = (%s * hlookup) * " + "vlookup;\n}\n", + args.fUniformHandler->getUniformCStr(fProfileSizeVar), + fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(), + fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(), + args.fUniformHandler->getUniformCStr(fProfileSizeVar), + fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(), + fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(), + args.fOutputColor, args.fInputColor ? args.fInputColor : "half4(1)"); + } + +private: + void onSetData(const GrGLSLProgramDataManager& pdman, + const GrFragmentProcessor& _proc) override { + const GrRectBlurEffect& _outer = _proc.cast<GrRectBlurEffect>(); + { + const SkRect rectValue = _outer.rect(); + pdman.set4fv(fRectVar, 1, (float*)&rectValue); + } + UniformHandle& rect = fRectVar; + (void)rect; + auto sigma = _outer.sigma(); + (void)sigma; + UniformHandle& blurProfile = fBlurProfileVar; + (void)blurProfile; + UniformHandle& proxyRectHalf = fProxyRectHalfVar; + (void)proxyRectHalf; + UniformHandle& proxyRectFloat = fProxyRectFloatVar; + (void)proxyRectFloat; + UniformHandle& profileSize = fProfileSizeVar; + (void)profileSize; + + pdman.set1f(profileSize, SkScalarCeilToScalar(6 * sigma)); + } + bool highPrecision; + UniformHandle fProxyRectHalfVar; + UniformHandle fProxyRectFloatVar; + UniformHandle fProfileSizeVar; + UniformHandle fRectVar; + UniformHandle fBlurProfileVar; +}; +GrGLSLFragmentProcessor* GrRectBlurEffect::onCreateGLSLInstance() const { + return new GrGLSLRectBlurEffect(); +} +void GrRectBlurEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, + GrProcessorKeyBuilder* b) const {} +bool GrRectBlurEffect::onIsEqual(const GrFragmentProcessor& other) const { + const GrRectBlurEffect& that = other.cast<GrRectBlurEffect>(); + (void)that; + if (fRect != that.fRect) return false; + if (fSigma != that.fSigma) return false; + if (fBlurProfile != that.fBlurProfile) return false; + return true; +} +GrRectBlurEffect::GrRectBlurEffect(const GrRectBlurEffect& src) + : INHERITED(kGrRectBlurEffect_ClassID, src.optimizationFlags()) + , fRect(src.fRect) + , fSigma(src.fSigma) + , fBlurProfile(src.fBlurProfile) { + this->addTextureSampler(&fBlurProfile); +} +std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::clone() const { + return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(*this)); +} +GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRectBlurEffect); +#if GR_TEST_UTILS +std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::TestCreate(GrProcessorTestData* data) { + float sigma = data->fRandom->nextRangeF(3, 8); + float width = data->fRandom->nextRangeF(200, 300); + float height = data->fRandom->nextRangeF(200, 300); + return GrRectBlurEffect::Make(data->resourceProvider(), SkRect::MakeWH(width, height), sigma); +} +#endif +#endif diff --git a/src/gpu/effects/GrRectBlurEffect.fp b/src/gpu/effects/GrRectBlurEffect.fp new file mode 100644 index 0000000000..fe5d59ed0b --- /dev/null +++ b/src/gpu/effects/GrRectBlurEffect.fp @@ -0,0 +1,123 @@ +@header { + #include "GrResourceProvider.h" + #include "../effects/SkBlurMask.h" +} + +in uniform float4 rect; +in float sigma; +in uniform sampler2D blurProfile; + +// 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. +layout(key) bool highPrecision = abs(rect.x) > 16000 || abs(rect.y) > 16000 || + abs(rect.z) > 16000 || abs(rect.w) > 16000 || + abs(rect.z - rect.x) > 16000 || abs(rect.w - rect.y) > 16000; + +layout(when=!highPrecision) uniform half4 proxyRectHalf; +layout(when=highPrecision) uniform float4 proxyRectFloat; +uniform half profileSize; + + +@class { + static sk_sp<GrTextureProxy> 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; + } +} + +@make { + 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; + } + + return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(rect, sigma, + std::move(blurProfile))); + } +} + +void main() { + @if (highPrecision) { + float2 translatedPos = sk_FragCoord.xy - rect.xy; + float width = rect.z - rect.x; + float height = rect.w - rect.y; + float2 smallDims = float2(width - profileSize, height - profileSize); + float center = 2 * floor(profileSize / 2 + 0.25) - 1; + float2 wh = smallDims - float2(center, center); + half hcoord = ((abs(translatedPos.x - 0.5 * width) - 0.5 * wh.x)) / profileSize; + half hlookup = texture(blurProfile, float2(hcoord, 0.5)).a; + half vcoord = ((abs(translatedPos.y - 0.5 * height) - 0.5 * wh.y)) / profileSize; + half vlookup = texture(blurProfile, float2(vcoord, 0.5)).a; + sk_OutColor = sk_InColor * hlookup * vlookup; + } else { + half2 translatedPos = sk_FragCoord.xy - rect.xy; + half width = rect.z - rect.x; + half height = rect.w - rect.y; + half2 smallDims = half2(width - profileSize, height - profileSize); + half center = 2 * floor(profileSize / 2 + 0.25) - 1; + half2 wh = smallDims - float2(center, center); + half hcoord = ((abs(translatedPos.x - 0.5 * width) - 0.5 * wh.x)) / profileSize; + half hlookup = texture(blurProfile, float2(hcoord, 0.5)).a; + half vcoord = ((abs(translatedPos.y - 0.5 * height) - 0.5 * wh.y)) / profileSize; + half vlookup = texture(blurProfile, float2(vcoord, 0.5)).a; + sk_OutColor = sk_InColor * hlookup * vlookup; + } +} + +@setData(pdman) { + pdman.set1f(profileSize, SkScalarCeilToScalar(6 * sigma)); +} + +@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag } + +@test(data) { + float sigma = data->fRandom->nextRangeF(3,8); + float width = data->fRandom->nextRangeF(200,300); + float height = data->fRandom->nextRangeF(200,300); + return GrRectBlurEffect::Make(data->resourceProvider(), + SkRect::MakeWH(width, height), sigma); +} diff --git a/src/gpu/effects/GrRectBlurEffect.h b/src/gpu/effects/GrRectBlurEffect.h new file mode 100644 index 0000000000..7a8bc2c005 --- /dev/null +++ b/src/gpu/effects/GrRectBlurEffect.h @@ -0,0 +1,100 @@ +/* + * 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 GrRectBlurEffect.fp; do not modify. + */ +#ifndef GrRectBlurEffect_DEFINED +#define GrRectBlurEffect_DEFINED +#include "SkTypes.h" +#if SK_SUPPORT_GPU + +#include "GrResourceProvider.h" +#include "../effects/SkBlurMask.h" +#include "GrFragmentProcessor.h" +#include "GrCoordTransform.h" +#include "GrColorSpaceXform.h" +class GrRectBlurEffect : public GrFragmentProcessor { +public: + static sk_sp<GrTextureProxy> 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; + } + SkRect rect() const { return fRect; } + float sigma() const { return fSigma; } + + 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; + } + + return std::unique_ptr<GrFragmentProcessor>( + new GrRectBlurEffect(rect, sigma, std::move(blurProfile))); + } + GrRectBlurEffect(const GrRectBlurEffect& src); + std::unique_ptr<GrFragmentProcessor> clone() const override; + const char* name() const override { return "RectBlurEffect"; } + +private: + GrRectBlurEffect(SkRect rect, float sigma, sk_sp<GrTextureProxy> blurProfile) + : INHERITED(kGrRectBlurEffect_ClassID, + (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag) + , fRect(rect) + , fSigma(sigma) + , fBlurProfile(std::move(blurProfile)) { + this->addTextureSampler(&fBlurProfile); + } + GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; + void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; + bool onIsEqual(const GrFragmentProcessor&) const override; + GR_DECLARE_FRAGMENT_PROCESSOR_TEST + SkRect fRect; + float fSigma; + TextureSampler fBlurProfile; + typedef GrFragmentProcessor INHERITED; +}; +#endif +#endif diff --git a/src/gpu/effects/GrSimpleTextureEffect.cpp b/src/gpu/effects/GrSimpleTextureEffect.cpp index 2c44ce4111..c3634f5739 100644 --- a/src/gpu/effects/GrSimpleTextureEffect.cpp +++ b/src/gpu/effects/GrSimpleTextureEffect.cpp @@ -23,6 +23,10 @@ public: GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; const GrSimpleTextureEffect& _outer = args.fFp.cast<GrSimpleTextureEffect>(); (void)_outer; + auto colorXform = _outer.colorXform(); + (void)colorXform; + auto matrix = _outer.matrix(); + (void)matrix; fColorSpaceHelper.emitCode(args.fUniformHandler, _outer.colorXform().get()); SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); fragBuilder->codeAppendf( |