diff options
-rw-r--r-- | src/effects/GrCircleBlurFragmentProcessor.cpp | 554 | ||||
-rw-r--r-- | src/gpu/effects/GrDitherEffect.cpp | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrDitherEffect.fp | 4 |
3 files changed, 280 insertions, 280 deletions
diff --git a/src/effects/GrCircleBlurFragmentProcessor.cpp b/src/effects/GrCircleBlurFragmentProcessor.cpp index d05a7f5a20..5759fc47cf 100644 --- a/src/effects/GrCircleBlurFragmentProcessor.cpp +++ b/src/effects/GrCircleBlurFragmentProcessor.cpp @@ -6,227 +6,253 @@ */ /* - * This file was autogenerated from GrCircleBlurFragmentProcessor.fp; do not - * modify. + * This file was autogenerated from GrCircleBlurFragmentProcessor.fp; do not modify. */ #include "GrCircleBlurFragmentProcessor.h" #if SK_SUPPORT_GPU -#include "GrResourceProvider.h" - -static float make_unnormalized_half_kernel(float* halfKernel, - int halfKernelSize, float sigma) { - const float invSigma = 1.f / sigma; - const float b = -0.5f * invSigma * invSigma; - float tot = 0.0f; - - float t = 0.5f; - for (int i = 0; i < halfKernelSize; ++i) { - float value = expf(t * t * b); - tot += value; - halfKernel[i] = value; - t += 1.f; - } - return tot; -} - -static void make_half_kernel_and_summed_table(float* halfKernel, - float* summedHalfKernel, - int halfKernelSize, float sigma) { - const float tot = - 2.f * make_unnormalized_half_kernel(halfKernel, halfKernelSize, sigma); - float sum = 0.f; - for (int i = 0; i < halfKernelSize; ++i) { - halfKernel[i] /= tot; - sum += halfKernel[i]; - summedHalfKernel[i] = sum; - } -} - -void apply_kernel_in_y(float* results, int numSteps, float firstX, - float circleR, int halfKernelSize, - const float* summedHalfKernelTable) { - float x = firstX; - for (int i = 0; i < numSteps; ++i, x += 1.f) { - if (x < -circleR || x > circleR) { - results[i] = 0; - continue; + #include "GrResourceProvider.h" + + + + static float make_unnormalized_half_kernel(float* halfKernel, int halfKernelSize, float sigma) { + const float invSigma = 1.f / sigma; + const float b = -0.5f * invSigma * invSigma; + float tot = 0.0f; + + float t = 0.5f; + for (int i = 0; i < halfKernelSize; ++i) { + float value = expf(t * t * b); + tot += value; + halfKernel[i] = value; + t += 1.f; + } + return tot; } - float y = sqrtf(circleR * circleR - x * x); - y -= 0.5f; - int yInt = SkScalarFloorToInt(y); - SkASSERT(yInt >= -1); - if (y < 0) { - results[i] = (y + 0.5f) * summedHalfKernelTable[0]; - } else if (yInt >= halfKernelSize - 1) { - results[i] = 0.5f; - } else { - float yFrac = y - yInt; - results[i] = (1.f - yFrac) * summedHalfKernelTable[yInt] + - yFrac * summedHalfKernelTable[yInt + 1]; + + + static void make_half_kernel_and_summed_table(float* halfKernel, float* summedHalfKernel, + int halfKernelSize, float sigma) { + + const float tot = 2.f * make_unnormalized_half_kernel(halfKernel, halfKernelSize, sigma); + float sum = 0.f; + for (int i = 0; i < halfKernelSize; ++i) { + halfKernel[i] /= tot; + sum += halfKernel[i]; + summedHalfKernel[i] = sum; + } } - } -} - -static uint8_t eval_at(float evalX, float circleR, const float* halfKernel, - int halfKernelSize, const float* yKernelEvaluations) { - float acc = 0; - float x = evalX - halfKernelSize; - for (int i = 0; i < halfKernelSize; ++i, x += 1.f) { - if (x < -circleR || x > circleR) { - continue; - } - float verticalEval = yKernelEvaluations[i]; - acc += verticalEval * halfKernel[halfKernelSize - i - 1]; - } - for (int i = 0; i < halfKernelSize; ++i, x += 1.f) { - if (x < -circleR || x > circleR) { - continue; + + + void apply_kernel_in_y(float* results, int numSteps, float firstX, float circleR, + int halfKernelSize, const float* summedHalfKernelTable) { + float x = firstX; + for (int i = 0; i < numSteps; ++i, x += 1.f) { + if (x < -circleR || x > circleR) { + results[i] = 0; + continue; + } + float y = sqrtf(circleR * circleR - x * x); + + + y -= 0.5f; + int yInt = SkScalarFloorToInt(y); + SkASSERT(yInt >= -1); + if (y < 0) { + results[i] = (y + 0.5f) * summedHalfKernelTable[0]; + } else if (yInt >= halfKernelSize - 1) { + results[i] = 0.5f; + } else { + float yFrac = y - yInt; + results[i] = (1.f - yFrac) * summedHalfKernelTable[yInt] + + yFrac * summedHalfKernelTable[yInt + 1]; + } + } } - float verticalEval = yKernelEvaluations[i + halfKernelSize]; - acc += verticalEval * halfKernel[i]; - } - - return SkUnitScalarClampToByte(2.f * acc); -} - -static uint8_t* create_circle_profile(float sigma, float circleR, - int profileTextureWidth) { - const int numSteps = profileTextureWidth; - uint8_t* weights = new uint8_t[numSteps]; - - int halfKernelSize = SkScalarCeilToInt(6.0f * sigma); - - halfKernelSize = ((halfKernelSize + 1) & ~1) >> 1; - - int numYSteps = numSteps + 2 * halfKernelSize; - - SkAutoTArray<float> bulkAlloc(halfKernelSize + halfKernelSize + numYSteps); - float* halfKernel = bulkAlloc.get(); - float* summedKernel = bulkAlloc.get() + halfKernelSize; - float* yEvals = bulkAlloc.get() + 2 * halfKernelSize; - make_half_kernel_and_summed_table(halfKernel, summedKernel, halfKernelSize, - sigma); - - float firstX = -halfKernelSize + 0.5f; - apply_kernel_in_y(yEvals, numYSteps, firstX, circleR, halfKernelSize, - summedKernel); - - for (int i = 0; i < numSteps - 1; ++i) { - float evalX = i + 0.5f; - weights[i] = - eval_at(evalX, circleR, halfKernel, halfKernelSize, yEvals + i); - } - - weights[numSteps - 1] = 0; - return weights; -} - -static uint8_t* create_half_plane_profile(int profileWidth) { - SkASSERT(!(profileWidth & 0x1)); - - float sigma = profileWidth / 6.f; - int halfKernelSize = profileWidth / 2; - - SkAutoTArray<float> halfKernel(halfKernelSize); - uint8_t* profile = new uint8_t[profileWidth]; - const float tot = 2.f * make_unnormalized_half_kernel(halfKernel.get(), - halfKernelSize, sigma); - float sum = 0.f; - - for (int i = 0; i < halfKernelSize; ++i) { - halfKernel[halfKernelSize - i - 1] /= tot; - sum += halfKernel[halfKernelSize - i - 1]; - profile[profileWidth - i - 1] = SkUnitScalarClampToByte(sum); - } - - for (int i = 0; i < halfKernelSize; ++i) { - sum += halfKernel[i]; - profile[halfKernelSize - i - 1] = SkUnitScalarClampToByte(sum); - } - - profile[profileWidth - 1] = 0; - return profile; -} - -static sk_sp<GrTextureProxy> create_profile_texture( - GrResourceProvider* resourceProvider, const SkRect& circle, float sigma, - float* solidRadius, float* textureRadius) { - float circleR = circle.width() / 2.0f; - - SkScalar sigmaToCircleRRatio = sigma / circleR; - - sigmaToCircleRRatio = SkTMin(sigmaToCircleRRatio, 8.f); - SkFixed sigmaToCircleRRatioFixed; - static const SkScalar kHalfPlaneThreshold = 0.1f; - bool useHalfPlaneApprox = false; - if (sigmaToCircleRRatio <= kHalfPlaneThreshold) { - useHalfPlaneApprox = true; - sigmaToCircleRRatioFixed = 0; - *solidRadius = circleR - 3 * sigma; - *textureRadius = 6 * sigma; - } else { - sigmaToCircleRRatioFixed = SkScalarToFixed(sigmaToCircleRRatio); - - sigmaToCircleRRatioFixed &= ~0xff; - sigmaToCircleRRatio = SkFixedToScalar(sigmaToCircleRRatioFixed); - sigma = circleR * sigmaToCircleRRatio; - *solidRadius = 0; - *textureRadius = circleR + 3 * sigma; - } - - static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); - GrUniqueKey key; - GrUniqueKey::Builder builder(&key, kDomain, 1); - builder[0] = sigmaToCircleRRatioFixed; - builder.finish(); - - sk_sp<GrTextureProxy> blurProfile = - resourceProvider->findProxyByUniqueKey(key); - if (!blurProfile) { - static constexpr int kProfileTextureWidth = 512; - GrSurfaceDesc texDesc; - texDesc.fWidth = kProfileTextureWidth; - texDesc.fHeight = 1; - texDesc.fConfig = kAlpha_8_GrPixelConfig; - - std::unique_ptr<uint8_t[]> profile(nullptr); - if (useHalfPlaneApprox) { - profile.reset(create_half_plane_profile(kProfileTextureWidth)); - } else { - SkScalar scale = kProfileTextureWidth / *textureRadius; - profile.reset(create_circle_profile(sigma * scale, circleR * scale, - kProfileTextureWidth)); + + + + + static uint8_t eval_at(float evalX, float circleR, const float* halfKernel, int halfKernelSize, + const float* yKernelEvaluations) { + float acc = 0; + + float x = evalX - halfKernelSize; + for (int i = 0; i < halfKernelSize; ++i, x += 1.f) { + if (x < -circleR || x > circleR) { + continue; + } + float verticalEval = yKernelEvaluations[i]; + acc += verticalEval * halfKernel[halfKernelSize - i - 1]; + } + for (int i = 0; i < halfKernelSize; ++i, x += 1.f) { + if (x < -circleR || x > circleR) { + continue; + } + float verticalEval = yKernelEvaluations[i + halfKernelSize]; + acc += verticalEval * halfKernel[i]; + } + + + return SkUnitScalarClampToByte(2.f * acc); } - blurProfile = GrSurfaceProxy::MakeDeferred( - resourceProvider, texDesc, SkBudgeted::kYes, profile.get(), 0); - if (!blurProfile) { - return nullptr; + + + + + + + + static uint8_t* create_circle_profile(float sigma, float circleR, int profileTextureWidth) { + const int numSteps = profileTextureWidth; + uint8_t* weights = new uint8_t[numSteps]; + + + int halfKernelSize = SkScalarCeilToInt(6.0f*sigma); + + halfKernelSize = ((halfKernelSize + 1) & ~1) >> 1; + + + int numYSteps = numSteps + 2 * halfKernelSize; + + SkAutoTArray<float> bulkAlloc(halfKernelSize + halfKernelSize + numYSteps); + float* halfKernel = bulkAlloc.get(); + float* summedKernel = bulkAlloc.get() + halfKernelSize; + float* yEvals = bulkAlloc.get() + 2 * halfKernelSize; + make_half_kernel_and_summed_table(halfKernel, summedKernel, halfKernelSize, sigma); + + float firstX = -halfKernelSize + 0.5f; + apply_kernel_in_y(yEvals, numYSteps, firstX, circleR, halfKernelSize, summedKernel); + + for (int i = 0; i < numSteps - 1; ++i) { + float evalX = i + 0.5f; + weights[i] = eval_at(evalX, circleR, halfKernel, halfKernelSize, yEvals + i); + } + + weights[numSteps - 1] = 0; + return weights; } - resourceProvider->assignUniqueKeyToProxy(key, blurProfile.get()); - } + static uint8_t* create_half_plane_profile(int profileWidth) { + SkASSERT(!(profileWidth & 0x1)); + + float sigma = profileWidth / 6.f; + int halfKernelSize = profileWidth / 2; + + SkAutoTArray<float> halfKernel(halfKernelSize); + uint8_t* profile = new uint8_t[profileWidth]; + + + const float tot = 2.f * make_unnormalized_half_kernel(halfKernel.get(), halfKernelSize, + sigma); + float sum = 0.f; + + for (int i = 0; i < halfKernelSize; ++i) { + halfKernel[halfKernelSize - i - 1] /= tot; + sum += halfKernel[halfKernelSize - i - 1]; + profile[profileWidth - i - 1] = SkUnitScalarClampToByte(sum); + } + + + for (int i = 0; i < halfKernelSize; ++i) { + sum += halfKernel[i]; + profile[halfKernelSize - i - 1] = SkUnitScalarClampToByte(sum); + } + + profile[profileWidth - 1] = 0; + return profile; + } - return blurProfile; -} + static sk_sp<GrTextureProxy> create_profile_texture(GrResourceProvider* resourceProvider, + const SkRect& circle, + float sigma, + float* solidRadius, float* textureRadius) { + float circleR = circle.width() / 2.0f; + + + SkScalar sigmaToCircleRRatio = sigma / circleR; + + + + + sigmaToCircleRRatio = SkTMin(sigmaToCircleRRatio, 8.f); + SkFixed sigmaToCircleRRatioFixed; + static const SkScalar kHalfPlaneThreshold = 0.1f; + bool useHalfPlaneApprox = false; + if (sigmaToCircleRRatio <= kHalfPlaneThreshold) { + useHalfPlaneApprox = true; + sigmaToCircleRRatioFixed = 0; + *solidRadius = circleR - 3 * sigma; + *textureRadius = 6 * sigma; + } else { + + sigmaToCircleRRatioFixed = SkScalarToFixed(sigmaToCircleRRatio); + + + sigmaToCircleRRatioFixed &= ~0xff; + sigmaToCircleRRatio = SkFixedToScalar(sigmaToCircleRRatioFixed); + sigma = circleR * sigmaToCircleRRatio; + *solidRadius = 0; + *textureRadius = circleR + 3 * sigma; + } + + static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); + GrUniqueKey key; + GrUniqueKey::Builder builder(&key, kDomain, 1); + builder[0] = sigmaToCircleRRatioFixed; + builder.finish(); + + sk_sp<GrTextureProxy> blurProfile = resourceProvider->findProxyByUniqueKey(key); + if (!blurProfile) { + static constexpr int kProfileTextureWidth = 512; + GrSurfaceDesc texDesc; + texDesc.fWidth = kProfileTextureWidth; + texDesc.fHeight = 1; + texDesc.fConfig = kAlpha_8_GrPixelConfig; + + std::unique_ptr<uint8_t[]> profile(nullptr); + if (useHalfPlaneApprox) { + profile.reset(create_half_plane_profile(kProfileTextureWidth)); + } else { + + SkScalar scale = kProfileTextureWidth / *textureRadius; + profile.reset(create_circle_profile(sigma * scale, circleR * scale, + kProfileTextureWidth)); + } + + blurProfile = GrSurfaceProxy::MakeDeferred(resourceProvider, + texDesc, SkBudgeted::kYes, profile.get(), 0); + if (!blurProfile) { + return nullptr; + } + + resourceProvider->assignUniqueKeyToProxy(key, blurProfile.get()); + } + + return blurProfile; + } -sk_sp<GrFragmentProcessor> GrCircleBlurFragmentProcessor::Make( - GrResourceProvider* resourceProvider, const SkRect& circle, float sigma) { - float solidRadius; - float textureRadius; - sk_sp<GrTextureProxy> profile(create_profile_texture( - resourceProvider, circle, sigma, &solidRadius, &textureRadius)); - if (!profile) { - return nullptr; - } - return sk_sp<GrFragmentProcessor>( - new GrCircleBlurFragmentProcessor(circle, textureRadius, solidRadius, - std::move(profile), resourceProvider)); -} + sk_sp<GrFragmentProcessor> GrCircleBlurFragmentProcessor::Make( + GrResourceProvider* resourceProvider, + const SkRect& circle, + float sigma) { + float solidRadius; + float textureRadius; + sk_sp<GrTextureProxy> profile(create_profile_texture(resourceProvider, circle, sigma, + &solidRadius, &textureRadius)); + if (!profile) { + return nullptr; + } + return sk_sp<GrFragmentProcessor>(new GrCircleBlurFragmentProcessor(circle, + textureRadius, + solidRadius, + std::move(profile), + resourceProvider)); + } #include "glsl/GrGLSLColorSpaceXformHelper.h" #include "glsl/GrGLSLFragmentProcessor.h" #include "glsl/GrGLSLFragmentShaderBuilder.h" @@ -234,83 +260,57 @@ sk_sp<GrFragmentProcessor> GrCircleBlurFragmentProcessor::Make( #include "SkSLCPP.h" #include "SkSLUtil.h" class GrGLSLCircleBlurFragmentProcessor : public GrGLSLFragmentProcessor { - public: - GrGLSLCircleBlurFragmentProcessor() {} - void emitCode(EmitArgs& args) override { - GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - const GrCircleBlurFragmentProcessor& _outer = - args.fFp.cast<GrCircleBlurFragmentProcessor>(); - (void)_outer; - fCircleDataVar = args.fUniformHandler->addUniform( - kFragment_GrShaderFlag, kVec4f_GrSLType, kDefault_GrSLPrecision, - "circleData"); - fragBuilder->codeAppendf( - "vec2 vec = vec2((sk_FragCoord.x - %s.x) * %s.w, (sk_FragCoord.y - " - "%s.y) * %s.w);\nfloat dist = length(vec) + (0.5 - %s.z) * %s.w;\n%s = " - "%s * texture(%s, vec2(dist, 0.5)).%s.w;\n", - args.fUniformHandler->getUniformCStr(fCircleDataVar), - args.fUniformHandler->getUniformCStr(fCircleDataVar), - args.fUniformHandler->getUniformCStr(fCircleDataVar), - args.fUniformHandler->getUniformCStr(fCircleDataVar), - args.fUniformHandler->getUniformCStr(fCircleDataVar), - args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fOutputColor, - args.fInputColor ? args.fInputColor : "vec4(1)", - fragBuilder->getProgramBuilder() - ->samplerVariable(args.fTexSamplers[0]) - .c_str(), - fragBuilder->getProgramBuilder() - ->samplerSwizzle(args.fTexSamplers[0]) - .c_str()); - } - - private: - void onSetData(const GrGLSLProgramDataManager& data, - const GrFragmentProcessor& _proc) override { - const GrCircleBlurFragmentProcessor& _outer = - _proc.cast<GrCircleBlurFragmentProcessor>(); - auto circleRect = _outer.circleRect(); - (void)circleRect; - auto textureRadius = _outer.textureRadius(); - (void)textureRadius; - auto solidRadius = _outer.solidRadius(); - (void)solidRadius; - UniformHandle& blurProfileSampler = fBlurProfileSamplerVar; - (void)blurProfileSampler; - UniformHandle& circleData = fCircleDataVar; - (void)circleData; - - data.set4f(circleData, circleRect.centerX(), circleRect.centerY(), - solidRadius, 1.f / textureRadius); - } - UniformHandle fCircleDataVar; - UniformHandle fBlurProfileSamplerVar; +public: + GrGLSLCircleBlurFragmentProcessor() {} + void emitCode(EmitArgs& args) override { + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; + const GrCircleBlurFragmentProcessor& _outer = args.fFp.cast<GrCircleBlurFragmentProcessor>(); + (void) _outer; + fCircleDataVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, kDefault_GrSLPrecision, "circleData"); + fragBuilder->codeAppendf("vec2 vec = vec2((sk_FragCoord.x - %s.x) * %s.w, (sk_FragCoord.y - %s.y) * %s.w);\nfloat dist = length(vec) + (0.5 - %s.z) * %s.w;\n%s = %s * texture(%s, vec2(dist, 0.5)).%s.w;\n", args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fOutputColor, args.fInputColor ? args.fInputColor : "vec4(1)", fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(), fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str()); + } +private: + void onSetData(const GrGLSLProgramDataManager& data, const GrFragmentProcessor& _proc) override { + const GrCircleBlurFragmentProcessor& _outer = _proc.cast<GrCircleBlurFragmentProcessor>(); + auto circleRect = _outer.circleRect(); + (void) circleRect; + auto textureRadius = _outer.textureRadius(); + (void) textureRadius; + auto solidRadius = _outer.solidRadius(); + (void) solidRadius; + UniformHandle& blurProfileSampler = fBlurProfileSamplerVar; + (void) blurProfileSampler; + UniformHandle& circleData = fCircleDataVar; + (void) circleData; + + data.set4f(circleData, circleRect.centerX(), circleRect.centerY(), solidRadius, + 1.f / textureRadius); + } + UniformHandle fCircleDataVar; + UniformHandle fBlurProfileSamplerVar; }; -GrGLSLFragmentProcessor* GrCircleBlurFragmentProcessor::onCreateGLSLInstance() - const { - return new GrGLSLCircleBlurFragmentProcessor(); +GrGLSLFragmentProcessor* GrCircleBlurFragmentProcessor::onCreateGLSLInstance() const { + return new GrGLSLCircleBlurFragmentProcessor(); } -void GrCircleBlurFragmentProcessor::onGetGLSLProcessorKey( - const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {} -bool GrCircleBlurFragmentProcessor::onIsEqual( - const GrFragmentProcessor& other) const { - const GrCircleBlurFragmentProcessor& that = - other.cast<GrCircleBlurFragmentProcessor>(); - (void)that; - if (fCircleRect != that.fCircleRect) return false; - if (fTextureRadius != that.fTextureRadius) return false; - if (fSolidRadius != that.fSolidRadius) return false; - if (fBlurProfileSampler != that.fBlurProfileSampler) return false; - return true; +void GrCircleBlurFragmentProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const { +} +bool GrCircleBlurFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const { + const GrCircleBlurFragmentProcessor& that = other.cast<GrCircleBlurFragmentProcessor>(); + (void) that; + if (fCircleRect != that.fCircleRect) return false; + if (fTextureRadius != that.fTextureRadius) return false; + if (fSolidRadius != that.fSolidRadius) return false; + if (fBlurProfileSampler != that.fBlurProfileSampler) return false; + return true; } GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrCircleBlurFragmentProcessor); #if GR_TEST_UTILS -sk_sp<GrFragmentProcessor> GrCircleBlurFragmentProcessor::TestCreate( - GrProcessorTestData* testData) { - SkScalar wh = testData->fRandom->nextRangeScalar(100.f, 1000.f); - SkScalar sigma = testData->fRandom->nextRangeF(1.f, 10.f); - SkRect circle = SkRect::MakeWH(wh, wh); - return GrCircleBlurFragmentProcessor::Make(testData->resourceProvider(), - circle, sigma); +sk_sp<GrFragmentProcessor> GrCircleBlurFragmentProcessor::TestCreate(GrProcessorTestData* testData) { + + SkScalar wh = testData->fRandom->nextRangeScalar(100.f, 1000.f); + SkScalar sigma = testData->fRandom->nextRangeF(1.f,10.f); + SkRect circle = SkRect::MakeWH(wh, wh); + return GrCircleBlurFragmentProcessor::Make(testData->resourceProvider(), circle, sigma); } #endif #endif diff --git a/src/gpu/effects/GrDitherEffect.cpp b/src/gpu/effects/GrDitherEffect.cpp index 370e0eedd1..052ed4e36d 100644 --- a/src/gpu/effects/GrDitherEffect.cpp +++ b/src/gpu/effects/GrDitherEffect.cpp @@ -23,7 +23,7 @@ public: GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; const GrDitherEffect& _outer = args.fFp.cast<GrDitherEffect>(); (void) _outer; - fragBuilder->codeAppendf("float r = fract(sin(dot(sk_FragCoord.xy, vec2(12.989800000000001, 78.233000000000004))) * 43758.545299999998);\n%s = clamp(0.0039215686274509803 * vec4(r) + %s, 0.0, 1.0);\n", args.fOutputColor, args.fInputColor ? args.fInputColor : "vec4(1)"); + fragBuilder->codeAppendf("float r = fract(sin(dot(sk_FragCoord.xy, vec2(12.989800000000001, 78.233000000000004))) * 43758.545299999998) - 0.5;\n%s = clamp(0.0039215686274509803 * vec4(r) + %s, 0.0, 1.0);\n", args.fOutputColor, args.fInputColor ? args.fInputColor : "vec4(1)"); } private: void onSetData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& _proc) override { diff --git a/src/gpu/effects/GrDitherEffect.fp b/src/gpu/effects/GrDitherEffect.fp index 77ff009113..1c35b38cd2 100644 --- a/src/gpu/effects/GrDitherEffect.fp +++ b/src/gpu/effects/GrDitherEffect.fp @@ -8,8 +8,8 @@ void main() { // For each channel c, add the random offset to the pixel to either bump // it up or let it remain constant during quantization. - float r = fract(sin(dot(sk_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453); - sk_OutColor = clamp(1.0 / 255.0 * vec4(r) + sk_InColor, 0, 1); + float r = fract(sin(dot(sk_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453) - .5; + sk_OutColor = clamp(1 / 255.0 * vec4(r) + sk_InColor, 0, 1); } @test(testData) { |