diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/effects/GrAlphaThresholdFragmentProcessor.cpp | 5 | ||||
-rw-r--r-- | src/effects/GrAlphaThresholdFragmentProcessor.fp | 11 | ||||
-rw-r--r-- | src/effects/GrAlphaThresholdFragmentProcessor.h | 7 | ||||
-rw-r--r-- | src/effects/GrCircleBlurFragmentProcessor.cpp | 595 | ||||
-rw-r--r-- | src/effects/GrCircleBlurFragmentProcessor.fp | 289 | ||||
-rw-r--r-- | src/effects/GrCircleBlurFragmentProcessor.h | 83 | ||||
-rw-r--r-- | src/gpu/effects/GrDitherEffect.cpp | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrDitherEffect.h | 3 | ||||
-rw-r--r-- | src/sksl/SkSLCPPCodeGenerator.cpp | 4 | ||||
-rw-r--r-- | src/sksl/SkSLHCodeGenerator.cpp | 5 |
10 files changed, 391 insertions, 613 deletions
diff --git a/src/effects/GrAlphaThresholdFragmentProcessor.cpp b/src/effects/GrAlphaThresholdFragmentProcessor.cpp index dd26ac5ffd..51869f3c46 100644 --- a/src/effects/GrAlphaThresholdFragmentProcessor.cpp +++ b/src/effects/GrAlphaThresholdFragmentProcessor.cpp @@ -9,8 +9,8 @@ * This file was autogenerated from GrAlphaThresholdFragmentProcessor.fp; do not modify. */ #include "GrAlphaThresholdFragmentProcessor.h" -#if SK_SUPPORT_GPU + #if SK_SUPPORT_GPU inline GrFragmentProcessor::OptimizationFlags GrAlphaThresholdFragmentProcessor::optFlags( float outerThreshold) { if (outerThreshold >= 1.0) { @@ -98,4 +98,5 @@ sk_sp<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::TestCreate(GrProce bounds); } #endif -#endif + + #endif diff --git a/src/effects/GrAlphaThresholdFragmentProcessor.fp b/src/effects/GrAlphaThresholdFragmentProcessor.fp index b576ecf086..1cc38c6d76 100644 --- a/src/effects/GrAlphaThresholdFragmentProcessor.fp +++ b/src/effects/GrAlphaThresholdFragmentProcessor.fp @@ -45,10 +45,17 @@ in uniform float outerThreshold; } @header { + #include "SkTypes.h" + #if SK_SUPPORT_GPU #include "GrColorSpaceXform.h" } +@headerEnd { + #endif +} + @cpp { + #if SK_SUPPORT_GPU inline GrFragmentProcessor::OptimizationFlags GrAlphaThresholdFragmentProcessor::optFlags( float outerThreshold) { if (outerThreshold >= 1.0) { @@ -60,6 +67,10 @@ in uniform float outerThreshold; } } +@cppEnd { + #endif +} + void main() { vec4 color = texture(image, sk_TransformedCoords2D[0], colorXform); vec4 mask_color = texture(mask, sk_TransformedCoords2D[1]); diff --git a/src/effects/GrAlphaThresholdFragmentProcessor.h b/src/effects/GrAlphaThresholdFragmentProcessor.h index 702b6aeb88..80e4e0b718 100644 --- a/src/effects/GrAlphaThresholdFragmentProcessor.h +++ b/src/effects/GrAlphaThresholdFragmentProcessor.h @@ -10,9 +10,9 @@ */ #ifndef GrAlphaThresholdFragmentProcessor_DEFINED #define GrAlphaThresholdFragmentProcessor_DEFINED -#include "SkTypes.h" -#if SK_SUPPORT_GPU + #include "SkTypes.h" + #if SK_SUPPORT_GPU #include "GrColorSpaceXform.h" #include "GrFragmentProcessor.h" #include "GrCoordTransform.h" @@ -75,5 +75,6 @@ private: float fOuterThreshold; typedef GrFragmentProcessor INHERITED; }; -#endif + + #endif #endif diff --git a/src/effects/GrCircleBlurFragmentProcessor.cpp b/src/effects/GrCircleBlurFragmentProcessor.cpp index b5cb961d5e..d99f0c78ba 100644 --- a/src/effects/GrCircleBlurFragmentProcessor.cpp +++ b/src/effects/GrCircleBlurFragmentProcessor.cpp @@ -1,316 +1,359 @@ /* - * Copyright 2017 Google Inc. + * Copyright 2015 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 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; +#include "GrContext.h" +#include "GrResourceProvider.h" +#include "glsl/GrGLSLFragmentProcessor.h" +#include "glsl/GrGLSLFragmentShaderBuilder.h" +#include "glsl/GrGLSLProgramDataManager.h" +#include "glsl/GrGLSLUniformHandler.h" + +#include "SkFixed.h" + +class GrCircleBlurFragmentProcessor::GLSLProcessor : public GrGLSLFragmentProcessor { +public: + void emitCode(EmitArgs&) override; + +protected: + void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override; + +private: + GrGLSLProgramDataManager::UniformHandle fDataUniform; + + typedef GrGLSLFragmentProcessor INHERITED; +}; + +void GrCircleBlurFragmentProcessor::GLSLProcessor::emitCode(EmitArgs& args) { + const char *dataName; + + // The data is formatted as: + // x,y - the center of the circle + // z - inner radius that should map to 0th entry in the texture. + // w - the inverse of the distance over which the texture is stretched. + fDataUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, + kVec4f_GrSLType, + kDefault_GrSLPrecision, + "data", + &dataName); + + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; + + if (args.fInputColor) { + fragBuilder->codeAppendf("vec4 src=%s;", args.fInputColor); + } else { + fragBuilder->codeAppendf("vec4 src=vec4(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; - } + // We just want to compute "(length(vec) - %s.z + 0.5) * %s.w" but need to rearrange + // for precision. + fragBuilder->codeAppendf("vec2 vec = vec2( (sk_FragCoord.x - %s.x) * %s.w, " + "(sk_FragCoord.y - %s.y) * %s.w );", + dataName, dataName, dataName, dataName); + fragBuilder->codeAppendf("float dist = length(vec) + (0.5 - %s.z) * %s.w;", + dataName, dataName); + + fragBuilder->codeAppendf("float intensity = "); + fragBuilder->appendTextureLookup(args.fTexSamplers[0], "vec2(dist, 0.5)"); + fragBuilder->codeAppend(".a;"); + + fragBuilder->codeAppendf("%s = src * intensity;\n", args.fOutputColor ); +} + +void GrCircleBlurFragmentProcessor::GLSLProcessor::onSetData(const GrGLSLProgramDataManager& pdman, + const GrFragmentProcessor& proc) { + const GrCircleBlurFragmentProcessor& cbfp = proc.cast<GrCircleBlurFragmentProcessor>(); + const SkRect& circle = cbfp.fCircle; + + // The data is formatted as: + // x,y - the center of the circle + // z - inner radius that should map to 0th entry in the texture. + // w - the inverse of the distance over which the profile texture is stretched. + pdman.set4f(fDataUniform, circle.centerX(), circle.centerY(), cbfp.fSolidRadius, + 1.f / cbfp.fTextureRadius); +} + +/////////////////////////////////////////////////////////////////////////////// + +GrCircleBlurFragmentProcessor::GrCircleBlurFragmentProcessor(const SkRect& circle, + float textureRadius, + float solidRadius, + sk_sp<GrTextureProxy> blurProfile) + : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag) + , fCircle(circle) + , fSolidRadius(solidRadius) + , fTextureRadius(textureRadius) + , fBlurProfileSampler(std::move(blurProfile), GrSamplerParams::kBilerp_FilterMode) { + this->initClassID<GrCircleBlurFragmentProcessor>(); + this->addTextureSampler(&fBlurProfileSampler); +} + +GrGLSLFragmentProcessor* GrCircleBlurFragmentProcessor::onCreateGLSLInstance() const { + return new GLSLProcessor; +} + +void GrCircleBlurFragmentProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps, + GrProcessorKeyBuilder* b) const { + // The code for this processor is always the same so there is nothing to add to the key. + return; +} + +// Computes an unnormalized half kernel (right side). Returns the summation of all the half kernel +// values. +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; + // Compute half kernel values at half pixel steps out from the center. + 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; +} - - - 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]; - } - } +// Create a Gaussian half-kernel (right side) and a summed area table given a sigma and number of +// discrete steps. The half kernel is normalized to sum to 0.5. +static void make_half_kernel_and_summed_table(float* halfKernel, float* summedHalfKernel, + int halfKernelSize, float sigma) { + // The half kernel should sum to 0.5 not 1.0. + 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]; +// Applies the 1D half kernel vertically at points along the x axis to a circle centered at the +// origin with radius circleR. +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; } - 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]; + float y = sqrtf(circleR * circleR - x * x); + // In the column at x we exit the circle at +y and -y + // The summed table entry j is actually reflects an offset of j + 0.5. + 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]; } - - - 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; - } +// Apply a Gaussian at point (evalX, 0) to a circle centered at the origin with radius circleR. +// This relies on having a half kernel computed for the Gaussian and a table of applications of +// the half kernel in y to columns at (evalX - halfKernel, evalX - halfKernel + 1, ..., evalX + +// halfKernel) passed in as yKernelEvaluations. +static uint8_t eval_at(float evalX, float circleR, const float* halfKernel, int halfKernelSize, + const float* yKernelEvaluations) { + float acc = 0; - 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); + float x = evalX - halfKernelSize; + for (int i = 0; i < halfKernelSize; ++i, x += 1.f) { + if (x < -circleR || x > circleR) { + continue; } - - - for (int i = 0; i < halfKernelSize; ++i) { - sum += halfKernel[i]; - profile[halfKernelSize - i - 1] = SkUnitScalarClampToByte(sum); + 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; } - - profile[profileWidth - 1] = 0; - return profile; + float verticalEval = yKernelEvaluations[i + halfKernelSize]; + acc += verticalEval * halfKernel[i]; } + // Since we applied a half kernel in y we multiply acc by 2 (the circle is symmetric about the + // x axis). + return SkUnitScalarClampToByte(2.f * acc); +} - 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; - } +// This function creates a profile of a blurred circle. It does this by computing a kernel for +// half the Gaussian and a matching summed area table. The summed area table is used to compute +// an array of vertical applications of the half kernel to the circle along the x axis. The table +// of y evaluations has 2 * k + n entries where k is the size of the half kernel and n is the size +// of the profile being computed. Then for each of the n profile entries we walk out k steps in each +// horizontal direction multiplying the corresponding y evaluation by the half kernel entry and +// sum these values to compute the profile entry. +static uint8_t* create_circle_profile(float sigma, float circleR, int profileTextureWidth) { + const int numSteps = profileTextureWidth; + uint8_t* weights = new uint8_t[numSteps]; - static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); - GrUniqueKey key; - GrUniqueKey::Builder builder(&key, kDomain, 1); - builder[0] = sigmaToCircleRRatioFixed; - builder.finish(); + // The full kernel is 6 sigmas wide. + int halfKernelSize = SkScalarCeilToInt(6.0f*sigma); + // round up to next multiple of 2 and then divide by 2 + halfKernelSize = ((halfKernelSize + 1) & ~1) >> 1; - 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()); - } + // Number of x steps at which to apply kernel in y to cover all the profile samples in x. + int numYSteps = numSteps + 2 * halfKernelSize; - return blurProfile; - } + 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); - 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)); + 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); } -#include "glsl/GrGLSLColorSpaceXformHelper.h" -#include "glsl/GrGLSLFragmentProcessor.h" -#include "glsl/GrGLSLFragmentShaderBuilder.h" -#include "glsl/GrGLSLProgramBuilder.h" -#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));\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()); + // Ensure the tail of the Gaussian goes to zero. + weights[numSteps - 1] = 0; + return weights; +} + +static uint8_t* create_half_plane_profile(int profileWidth) { + SkASSERT(!(profileWidth & 0x1)); + // The full kernel is 6 sigmas wide. + float sigma = profileWidth / 6.f; + int halfKernelSize = profileWidth / 2; + + SkAutoTArray<float> halfKernel(halfKernelSize); + uint8_t* profile = new uint8_t[profileWidth]; + + // The half kernel should sum to 0.5. + const float tot = 2.f * make_unnormalized_half_kernel(halfKernel.get(), halfKernelSize, sigma); + float sum = 0.f; + // Populate the profile from the right edge to the middle. + for (int i = 0; i < halfKernelSize; ++i) { + halfKernel[halfKernelSize - i - 1] /= tot; + sum += halfKernel[halfKernelSize - i - 1]; + profile[profileWidth - i - 1] = SkUnitScalarClampToByte(sum); } -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); + // Populate the profile from the middle to the left edge (by flipping the half kernel and + // continuing the summation). + for (int i = 0; i < halfKernelSize; ++i) { + sum += halfKernel[i]; + profile[halfKernelSize - i - 1] = SkUnitScalarClampToByte(sum); } - UniformHandle fCircleDataVar; - UniformHandle fBlurProfileSamplerVar; -}; -GrGLSLFragmentProcessor* GrCircleBlurFragmentProcessor::onCreateGLSLInstance() const { - return new GrGLSLCircleBlurFragmentProcessor(); + // Ensure tail goes to 0. + profile[profileWidth - 1] = 0; + return profile; } -void GrCircleBlurFragmentProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const { + +static sk_sp<GrTextureProxy> create_profile_texture(GrResourceProvider* resourceProvider, + const SkRect& circle, + float sigma, + float* solidRadius, float* textureRadius) { + float circleR = circle.width() / 2.0f; + // Profile textures are cached by the ratio of sigma to circle radius and by the size of the + // profile texture (binned by powers of 2). + SkScalar sigmaToCircleRRatio = sigma / circleR; + // When sigma is really small this becomes a equivalent to convolving a Gaussian with a half- + // plane. Similarly, in the extreme high ratio cases circle becomes a point WRT to the Guassian + // and the profile texture is a just a Gaussian evaluation. However, we haven't yet implemented + // this latter optimization. + 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 { + // Convert to fixed point for the key. + sigmaToCircleRRatioFixed = SkScalarToFixed(sigmaToCircleRRatio); + // We shave off some bits to reduce the number of unique entries. We could probably shave + // off more than we do. + 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 { + // Rescale params to the size of the texture we're creating. + 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; } -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; + +////////////////////////////////////////////////////////////////////////////// + +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))); } + +////////////////////////////////////////////////////////////////////////////// + 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); +#if GR_TEST_UTILS +sk_sp<GrFragmentProcessor> GrCircleBlurFragmentProcessor::TestCreate(GrProcessorTestData* d) { + SkScalar wh = d->fRandom->nextRangeScalar(100.f, 1000.f); + SkScalar sigma = d->fRandom->nextRangeF(1.f,10.f); SkRect circle = SkRect::MakeWH(wh, wh); - return GrCircleBlurFragmentProcessor::Make(testData->resourceProvider(), circle, sigma); + return GrCircleBlurFragmentProcessor::Make(d->resourceProvider(), circle, sigma); } #endif + #endif diff --git a/src/effects/GrCircleBlurFragmentProcessor.fp b/src/effects/GrCircleBlurFragmentProcessor.fp deleted file mode 100644 index 7682ad186e..0000000000 --- a/src/effects/GrCircleBlurFragmentProcessor.fp +++ /dev/null @@ -1,289 +0,0 @@ -in vec4 circleRect; -in float textureRadius; -in float solidRadius; -in uniform sampler2D blurProfileSampler; - -// The data is formatted as: -// x, y - the center of the circle -// z - inner radius that should map to 0th entry in the texture. -// w - the inverse of the distance over which the texture is stretched. -uniform vec4 circleData; - -@optimizationFlags { - kCompatibleWithCoverageAsAlpha_OptimizationFlag -} - -@constructorParams { - GrResourceProvider* resourceProvider -} - -@make { - static sk_sp<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider, - const SkRect& circle, float sigma); -} - -@setData(data) { - data.set4f(circleData, circleRect.centerX(), circleRect.centerY(), solidRadius, - 1.f / textureRadius); -} - -@cpp { - #include "GrResourceProvider.h" - - // Computes an unnormalized half kernel (right side). Returns the summation of all the half - // kernel values. - 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; - // Compute half kernel values at half pixel steps out from the center. - 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; - } - - // Create a Gaussian half-kernel (right side) and a summed area table given a sigma and number - // of discrete steps. The half kernel is normalized to sum to 0.5. - static void make_half_kernel_and_summed_table(float* halfKernel, float* summedHalfKernel, - int halfKernelSize, float sigma) { - // The half kernel should sum to 0.5 not 1.0. - 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; - } - } - - // Applies the 1D half kernel vertically at points along the x axis to a circle centered at the - // origin with radius circleR. - 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); - // In the column at x we exit the circle at +y and -y - // The summed table entry j is actually reflects an offset of j + 0.5. - 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]; - } - } - } - - // Apply a Gaussian at point (evalX, 0) to a circle centered at the origin with radius circleR. - // This relies on having a half kernel computed for the Gaussian and a table of applications of - // the half kernel in y to columns at (evalX - halfKernel, evalX - halfKernel + 1, ..., evalX + - // halfKernel) passed in as yKernelEvaluations. - 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]; - } - // Since we applied a half kernel in y we multiply acc by 2 (the circle is symmetric about - // the x axis). - return SkUnitScalarClampToByte(2.f * acc); - } - - // This function creates a profile of a blurred circle. It does this by computing a kernel for - // half the Gaussian and a matching summed area table. The summed area table is used to compute - // an array of vertical applications of the half kernel to the circle along the x axis. The - // table of y evaluations has 2 * k + n entries where k is the size of the half kernel and n is - // the size of the profile being computed. Then for each of the n profile entries we walk out k - // steps in each horizontal direction multiplying the corresponding y evaluation by the half - // kernel entry and sum these values to compute the profile entry. - static uint8_t* create_circle_profile(float sigma, float circleR, int profileTextureWidth) { - const int numSteps = profileTextureWidth; - uint8_t* weights = new uint8_t[numSteps]; - - // The full kernel is 6 sigmas wide. - int halfKernelSize = SkScalarCeilToInt(6.0f*sigma); - // round up to next multiple of 2 and then divide by 2 - halfKernelSize = ((halfKernelSize + 1) & ~1) >> 1; - - // Number of x steps at which to apply kernel in y to cover all the profile samples in x. - 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); - } - // Ensure the tail of the Gaussian goes to zero. - weights[numSteps - 1] = 0; - return weights; - } - - static uint8_t* create_half_plane_profile(int profileWidth) { - SkASSERT(!(profileWidth & 0x1)); - // The full kernel is 6 sigmas wide. - float sigma = profileWidth / 6.f; - int halfKernelSize = profileWidth / 2; - - SkAutoTArray<float> halfKernel(halfKernelSize); - uint8_t* profile = new uint8_t[profileWidth]; - - // The half kernel should sum to 0.5. - const float tot = 2.f * make_unnormalized_half_kernel(halfKernel.get(), halfKernelSize, - sigma); - float sum = 0.f; - // Populate the profile from the right edge to the middle. - for (int i = 0; i < halfKernelSize; ++i) { - halfKernel[halfKernelSize - i - 1] /= tot; - sum += halfKernel[halfKernelSize - i - 1]; - profile[profileWidth - i - 1] = SkUnitScalarClampToByte(sum); - } - // Populate the profile from the middle to the left edge (by flipping the half kernel and - // continuing the summation). - for (int i = 0; i < halfKernelSize; ++i) { - sum += halfKernel[i]; - profile[halfKernelSize - i - 1] = SkUnitScalarClampToByte(sum); - } - // Ensure tail goes to 0. - 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; - // Profile textures are cached by the ratio of sigma to circle radius and by the size of the - // profile texture (binned by powers of 2). - SkScalar sigmaToCircleRRatio = sigma / circleR; - // When sigma is really small this becomes a equivalent to convolving a Gaussian with a - // half-plane. Similarly, in the extreme high ratio cases circle becomes a point WRT to the - // Guassian and the profile texture is a just a Gaussian evaluation. However, we haven't yet - // implemented this latter optimization. - 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 { - // Convert to fixed point for the key. - sigmaToCircleRRatioFixed = SkScalarToFixed(sigmaToCircleRRatio); - // We shave off some bits to reduce the number of unique entries. We could probably - // shave off more than we do. - 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 { - // Rescale params to the size of the texture we're creating. - 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)); - } -} - -void main() { - // We just want to compute "(length(vec) - circleData.z + 0.5) * circleData.w" but need to - // rearrange for precision. - vec2 vec = vec2((sk_FragCoord.x - circleData.x) * circleData.w, - (sk_FragCoord.y - circleData.y) * circleData.w); - float dist = length(vec) + (0.5 - circleData.z) * circleData.w; - sk_OutColor = sk_InColor * texture(blurProfileSampler, vec2(dist, 0.5)); -} - -@test(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); -}
\ No newline at end of file diff --git a/src/effects/GrCircleBlurFragmentProcessor.h b/src/effects/GrCircleBlurFragmentProcessor.h index c01ea9b11d..3ed4cfc094 100644 --- a/src/effects/GrCircleBlurFragmentProcessor.h +++ b/src/effects/GrCircleBlurFragmentProcessor.h @@ -1,52 +1,73 @@ /* - * Copyright 2017 Google Inc. + * Copyright 2015 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 GrCircleBlurFragmentProcessor.fp; do not modify. - */ #ifndef GrCircleBlurFragmentProcessor_DEFINED #define GrCircleBlurFragmentProcessor_DEFINED + +#include "SkString.h" #include "SkTypes.h" + #if SK_SUPPORT_GPU + #include "GrFragmentProcessor.h" -#include "GrCoordTransform.h" -#include "effects/GrProxyMove.h" +#include "GrProcessorUnitTest.h" + +class GrResourceProvider; + +// This FP handles the special case of a blurred circle. It uses a 1D +// profile that is just rotated about the origin of the circle. class GrCircleBlurFragmentProcessor : public GrFragmentProcessor { public: - SkRect circleRect() const { return fCircleRect; } - float textureRadius() const { return fTextureRadius; } - float solidRadius() const { return fSolidRadius; } + static sk_sp<GrFragmentProcessor> Make(GrResourceProvider*, const SkRect& circle, float sigma); - static sk_sp<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider, - const SkRect& circle, float sigma); - const char* name() const override { return "CircleBlurFragmentProcessor"; } -private: - GrCircleBlurFragmentProcessor(SkRect circleRect, float textureRadius, float solidRadius, sk_sp<GrTextureProxy> blurProfileSampler, - GrResourceProvider* resourceProvider -) - : INHERITED((OptimizationFlags) - kCompatibleWithCoverageAsAlpha_OptimizationFlag -) - , fCircleRect(circleRect) - , fTextureRadius(textureRadius) - , fSolidRadius(solidRadius) - , fBlurProfileSampler(std::move(blurProfileSampler)) { - this->addTextureSampler(&fBlurProfileSampler); - this->initClassID<GrCircleBlurFragmentProcessor>(); + ~GrCircleBlurFragmentProcessor() override {} + + const char* name() const override { return "CircleBlur"; } + + SkString dumpInfo() const override { + SkString str; + str.appendf("Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], solidR: %.2f, textureR: %.2f", + fCircle.fLeft, fCircle.fTop, fCircle.fRight, fCircle.fBottom, + fSolidRadius, fTextureRadius); + return str; } + +private: + // This nested GLSL processor implementation is defined in the cpp file. + class GLSLProcessor; + + /** + * Creates a profile texture for the circle and sigma. The texture will have a height of 1. + * The x texture coord should map from 0 to 1 across the radius range of solidRadius to + * solidRadius + textureRadius. + */ + GrCircleBlurFragmentProcessor(const SkRect& circle, + float textureRadius, float innerRadius, + sk_sp<GrTextureProxy> blurProfile); + GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; - void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) const override; - bool onIsEqual(const GrFragmentProcessor&) const override; + + void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; + + bool onIsEqual(const GrFragmentProcessor& other) const override { + const GrCircleBlurFragmentProcessor& cbfp = other.cast<GrCircleBlurFragmentProcessor>(); + return fCircle == cbfp.fCircle && fSolidRadius == cbfp.fSolidRadius && + fTextureRadius == cbfp.fTextureRadius; + } + + SkRect fCircle; + SkScalar fSolidRadius; + float fTextureRadius; + TextureSampler fBlurProfileSampler; + GR_DECLARE_FRAGMENT_PROCESSOR_TEST - SkRect fCircleRect; - float fTextureRadius; - float fSolidRadius; - TextureSampler fBlurProfileSampler; + typedef GrFragmentProcessor INHERITED; }; + #endif #endif diff --git a/src/gpu/effects/GrDitherEffect.cpp b/src/gpu/effects/GrDitherEffect.cpp index 370e0eedd1..8c24d78843 100644 --- a/src/gpu/effects/GrDitherEffect.cpp +++ b/src/gpu/effects/GrDitherEffect.cpp @@ -9,7 +9,6 @@ * This file was autogenerated from GrDitherEffect.fp; do not modify. */ #include "GrDitherEffect.h" -#if SK_SUPPORT_GPU #include "glsl/GrGLSLColorSpaceXformHelper.h" #include "glsl/GrGLSLFragmentProcessor.h" #include "glsl/GrGLSLFragmentShaderBuilder.h" @@ -46,4 +45,3 @@ sk_sp<GrFragmentProcessor> GrDitherEffect::TestCreate(GrProcessorTestData* testD return GrDitherEffect::Make(); } #endif -#endif diff --git a/src/gpu/effects/GrDitherEffect.h b/src/gpu/effects/GrDitherEffect.h index d0bf9a9f9c..cbb626424c 100644 --- a/src/gpu/effects/GrDitherEffect.h +++ b/src/gpu/effects/GrDitherEffect.h @@ -10,8 +10,6 @@ */ #ifndef GrDitherEffect_DEFINED #define GrDitherEffect_DEFINED -#include "SkTypes.h" -#if SK_SUPPORT_GPU #include "GrFragmentProcessor.h" #include "GrCoordTransform.h" #include "effects/GrProxyMove.h" @@ -33,4 +31,3 @@ private: typedef GrFragmentProcessor INHERITED; }; #endif -#endif diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp index 9210dde7a3..09622f3e4c 100644 --- a/src/sksl/SkSLCPPCodeGenerator.cpp +++ b/src/sksl/SkSLCPPCodeGenerator.cpp @@ -542,8 +542,7 @@ bool CPPCodeGenerator::generateCode() { const char* baseName = fName.c_str(); const char* fullName = fFullName.c_str(); this->writef(kFragmentProcessorHeader, fullName); - this->writef("#include \"%s.h\"\n" - "#if SK_SUPPORT_GPU\n", fullName); + this->writef("#include \"%s.h\"\n", fullName); this->writeSection(CPP_SECTION); this->writef("#include \"glsl/GrGLSLColorSpaceXformHelper.h\"\n" "#include \"glsl/GrGLSLFragmentProcessor.h\"\n" @@ -594,7 +593,6 @@ bool CPPCodeGenerator::generateCode() { "}\n"); this->writeTest(); this->writeSection(CPP_END_SECTION); - this->write("#endif\n"); result &= 0 == fErrors.errorCount(); return result; } diff --git a/src/sksl/SkSLHCodeGenerator.cpp b/src/sksl/SkSLHCodeGenerator.cpp index cd3f7f2ec1..405fb0e6ce 100644 --- a/src/sksl/SkSLHCodeGenerator.cpp +++ b/src/sksl/SkSLHCodeGenerator.cpp @@ -201,8 +201,6 @@ bool HCodeGenerator::generateCode() { "#define %s_DEFINED\n", fFullName.c_str(), fFullName.c_str()); - this->writef("#include \"SkTypes.h\"\n" - "#if SK_SUPPORT_GPU\n"); this->writeSection(HEADER_SECTION); this->writef("#include \"GrFragmentProcessor.h\"\n" "#include \"GrCoordTransform.h\"\n" @@ -233,8 +231,7 @@ bool HCodeGenerator::generateCode() { this->writef(" typedef GrFragmentProcessor INHERITED;\n" "};\n"); this->writeSection(HEADER_END_SECTION); - this->writef("#endif\n" - "#endif\n"); + this->writef("#endif\n"); return 0 == fErrors.errorCount(); } |