From: dvonbeck Date: Fri, 29 Jul 2016 16:53:56 +0000 (-0700) Subject: GrFP can express distance vector field req., program builder declares variable for it X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~116^2~498 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4ef6dfa7089c092c67b0d5ec34e89c1e319af196;p=platform%2Fupstream%2FlibSkiaSharp.git GrFP can express distance vector field req., program builder declares variable for it This update allows fragment processors to require a field of vectors to the nearest edge. This requirement propagates: - from child FPs to their parent - from parent FPs to the GrPaint - from GrPaint through the PipelineBuilder into GrPipeline - acessed from GrPipeline by GrGLSLProgramBuilder GrGLSL generates a variable for the distance vector and passes it down to the GeometryProcessor->emitCode() method. This CL's base is the CL for adding the BevelNormalSource API: https://codereview.chromium.org/2080993002 BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2114993002 Review-Url: https://codereview.chromium.org/2114993002 --- diff --git a/gyp/core.gypi b/gyp/core.gypi index 6306a75..2c32c79 100644 --- a/gyp/core.gypi +++ b/gyp/core.gypi @@ -197,6 +197,7 @@ '<(skia_src_path)/core/SkNormalFlatSource.h', '<(skia_src_path)/core/SkNormalSource.cpp', '<(skia_src_path)/core/SkNormalSource.h', + '<(skia_src_path)/core/SkNormalSourcePriv.h', '<(skia_src_path)/core/SkNx.h', '<(skia_src_path)/core/SkOpts.cpp', '<(skia_src_path)/core/SkOpts.h', diff --git a/gyp/ports.gyp b/gyp/ports.gyp index 8080fe0..1950680 100644 --- a/gyp/ports.gyp +++ b/gyp/ports.gyp @@ -16,12 +16,14 @@ 'include_dirs': [ '../include/effects', '../include/client/android', + '../include/gpu', '../include/images', '../include/ports', '../include/private', '../include/utils', '../include/utils/win', '../src/core', + '../src/gpu', '../src/image', '../src/lazy', '../src/ports', diff --git a/include/gpu/GrFragmentProcessor.h b/include/gpu/GrFragmentProcessor.h index 4b56fbf..ffbf576 100644 --- a/include/gpu/GrFragmentProcessor.h +++ b/include/gpu/GrFragmentProcessor.h @@ -65,6 +65,7 @@ public: GrFragmentProcessor() : INHERITED() + , fUsesDistanceVectorField(false) , fUsesLocalCoords(false) , fNumTexturesExclChildren(0) , fNumBuffersExclChildren(0) @@ -110,6 +111,9 @@ public: /** Do any of the coordtransforms for this processor require local coords? */ bool usesLocalCoords() const { return fUsesLocalCoords; } + /** Does this FP need a vector to the nearest edge? */ + bool usesDistanceVectorField() const { return fUsesDistanceVectorField; } + /** Returns true if this and other processor conservatively draw identically. It can only return true when the two processor are of the same subclass (i.e. they return the same object from from getFactory()). @@ -173,6 +177,11 @@ protected: */ virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const = 0; + /* Sub-classes should set this to true in their constructors if they need access to a distance + * vector field to the nearest edge + */ + bool fUsesDistanceVectorField; + private: void notifyRefCntIsZero() const final; diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h index 8be1d50..ca9ba59 100644 --- a/include/gpu/GrPaint.h +++ b/include/gpu/GrPaint.h @@ -78,6 +78,11 @@ public: bool getAllowSRGBInputs() const { return fAllowSRGBInputs; } /** + * Does one of the fragment processors need a field of distance vectors to the nearest edge? + */ + bool usesDistanceVectorField() const { return fUsesDistanceVectorField; } + + /** * Should rendering be gamma-correct, end-to-end. Causes sRGB render targets to behave * as such (with linear blending), and sRGB inputs to be filtered and decoded correctly. */ @@ -101,6 +106,7 @@ public: */ void addColorFragmentProcessor(sk_sp fp) { SkASSERT(fp); + fUsesDistanceVectorField |= fp->usesDistanceVectorField(); fColorFragmentProcessors.push_back(std::move(fp)); } @@ -109,6 +115,7 @@ public: */ void addCoverageFragmentProcessor(sk_sp fp) { SkASSERT(fp); + fUsesDistanceVectorField |= fp->usesDistanceVectorField(); fCoverageFragmentProcessors.push_back(std::move(fp)); } @@ -142,6 +149,7 @@ public: fAntiAlias = paint.fAntiAlias; fDisableOutputConversionToSRGB = paint.fDisableOutputConversionToSRGB; fAllowSRGBInputs = paint.fAllowSRGBInputs; + fUsesDistanceVectorField = paint.fUsesDistanceVectorField; fColor = paint.fColor; fColorFragmentProcessors = paint.fColorFragmentProcessors; @@ -168,6 +176,7 @@ private: bool fAntiAlias; bool fDisableOutputConversionToSRGB; bool fAllowSRGBInputs; + bool fUsesDistanceVectorField; GrColor4f fColor; }; diff --git a/src/core/SkNormalBevelSource.cpp b/src/core/SkNormalBevelSource.cpp index feccb0c..a63e434 100644 --- a/src/core/SkNormalBevelSource.cpp +++ b/src/core/SkNormalBevelSource.cpp @@ -8,6 +8,7 @@ #include "SkNormalBevelSource.h" #include "SkNormalSource.h" +#include "SkNormalSourcePriv.h" #include "SkPoint3.h" #include "SkReadBuffer.h" #include "SkWriteBuffer.h" @@ -25,17 +26,19 @@ public: , fWidth(width) , fHeight(height) { this->initClassID(); + + fUsesDistanceVectorField = true; } - class GLSLNormalBevelFP : public GrGLSLFragmentProcessor { + class GLSLNormalBevelFP : public GLSLNormalFP { public: GLSLNormalBevelFP() { fPrevWidth = SkFloatToScalar(0.0f); fPrevHeight = SkFloatToScalar(0.0f); } - void emitCode(EmitArgs& args) override { - GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; + void onEmitCode(EmitArgs& args) override { + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; const char* widthUniName = nullptr; @@ -46,7 +49,7 @@ public: fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision, "Height", &heightUniName); - fragBuilder->codeAppendf("%s = vec4(0, 0, 1, 0);", args.fOutputColor); + fragBuilder->codeAppendf("%s = vec4(0.0, 0.0, 1.0, 0.0);", args.fOutputColor); } static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, @@ -56,7 +59,8 @@ public: } protected: - void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override { + void setNormalData(const GrGLSLProgramDataManager& pdman, + const GrProcessor& proc) override { const NormalBevelFP& normalBevelFP = proc.cast(); if (fPrevWidth != normalBevelFP.fWidth) { diff --git a/src/core/SkNormalFlatSource.cpp b/src/core/SkNormalFlatSource.cpp index fcb1a4f..bdd65b0 100644 --- a/src/core/SkNormalFlatSource.cpp +++ b/src/core/SkNormalFlatSource.cpp @@ -8,6 +8,7 @@ #include "SkNormalFlatSource.h" #include "SkNormalSource.h" +#include "SkNormalSourcePriv.h" #include "SkPoint3.h" #include "SkReadBuffer.h" #include "SkWriteBuffer.h" @@ -23,12 +24,12 @@ public: this->initClassID(); } - class GLSLNormalFlatFP : public GrGLSLFragmentProcessor { + class GLSLNormalFlatFP : public GLSLNormalFP { public: GLSLNormalFlatFP() {} - void emitCode(EmitArgs& args) override { - GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; + void onEmitCode(EmitArgs& args) override { + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; fragBuilder->codeAppendf("%s = vec4(0, 0, 1, 0);", args.fOutputColor); } @@ -39,7 +40,8 @@ public: } protected: - void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {} + void setNormalData(const GrGLSLProgramDataManager& pdman, + const GrProcessor& proc) override {} }; void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override { diff --git a/src/core/SkNormalMapSource.cpp b/src/core/SkNormalMapSource.cpp index 2ecf1d3..c2cda09 100644 --- a/src/core/SkNormalMapSource.cpp +++ b/src/core/SkNormalMapSource.cpp @@ -10,6 +10,7 @@ #include "SkLightingShader.h" #include "SkMatrix.h" #include "SkNormalSource.h" +#include "SkNormalSourcePriv.h" #include "SkPM4f.h" #include "SkReadBuffer.h" #include "SkWriteBuffer.h" @@ -31,13 +32,13 @@ public: this->initClassID(); } - class GLSLNormalMapFP : public GrGLSLFragmentProcessor { + class GLSLNormalMapFP : public GLSLNormalFP { public: GLSLNormalMapFP() : fColumnMajorInvCTM22{0.0f} {} - void emitCode(EmitArgs& args) override { - GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; + void onEmitCode(EmitArgs& args) override { + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; // add uniform @@ -78,7 +79,8 @@ public: } protected: - void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override { + void setNormalData(const GrGLSLProgramDataManager& pdman, + const GrProcessor& proc) override { const NormalMapFP& normalMapFP = proc.cast(); const SkMatrix& invCTM = normalMapFP.invCTM(); diff --git a/src/core/SkNormalSource.h b/src/core/SkNormalSource.h index 8cbb3e4..4b09d0b 100644 --- a/src/core/SkNormalSource.h +++ b/src/core/SkNormalSource.h @@ -111,7 +111,7 @@ public: /** Returns a normal source that generates a bevel for the given shape. UNIMPLEMENTED: Will return straight-up normals only. - @param type the type of bevel to add + @param type the type of bevel to add. @param width the width of the bevel, in source space. Must be positive. @param height the height of the plateau, in source space. Can be positive, negative, or zero. A negative height means the simulated bevels slope downwards. diff --git a/src/core/SkNormalSourcePriv.h b/src/core/SkNormalSourcePriv.h new file mode 100644 index 0000000..ce8baf6 --- /dev/null +++ b/src/core/SkNormalSourcePriv.h @@ -0,0 +1,57 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkNormalSourcePriv_DEFINED +#define SkNormalSourcePriv_DEFINED + +#if SK_SUPPORT_GPU +#include "glsl/GrGLSLFragmentProcessor.h" +#include "glsl/GrGLSLFragmentShaderBuilder.h" + +/* GLSLFragmentProcessors for NormalSourceImpls must sub-class this class and override onEmitCode, + * and setNormalData calls, as well as all other calls FPs normally override, except for the 2 + * defined in this superclass. + * This class exists to intercept emitCode calls and emit <0, 0, 1> if the FP requires a distance + * vector but the GP doesn't provide it. onSetData calls need to be intercepted too because + * uniform handlers will be invalid in subclasses where onEmitCode isn't called. + * We don't need to adjust the key here since the use of a given GP (through its class ID already in + * the key), will determine what code gets emitted here. + */ +class GLSLNormalFP : public GrGLSLFragmentProcessor { +public: + GLSLNormalFP() + : fDidIntercept(false) {} + + void emitCode(EmitArgs& args) final override { + if (args.fFp.usesDistanceVectorField() && !args.fGpImplementsDistanceVector) { + GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; + fragBuilder->codeAppendf("// GLSLNormalFP intercepted emitCode call, GP does not " + "implement required distance vector feature\n"); + fragBuilder->codeAppendf("%s = vec4(0, 0, 1, 0);", args.fOutputColor); + + fDidIntercept = true; + } else { + this->onEmitCode(args); + } + } + + void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) final override { + if (!fDidIntercept) { + this->setNormalData(pdman, proc); + } + } + +protected: + virtual void onEmitCode(EmitArgs& args) = 0; + virtual void setNormalData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) = 0; + +private: + bool fDidIntercept; +}; +#endif + +#endif diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp index fdba610..a8a4898 100644 --- a/src/gpu/GrFragmentProcessor.cpp +++ b/src/gpu/GrFragmentProcessor.cpp @@ -106,6 +106,9 @@ int GrFragmentProcessor::registerChildProcessor(sk_sp child if (child->usesLocalCoords()) { fUsesLocalCoords = true; } + if (child->usesDistanceVectorField()) { + fUsesDistanceVectorField = true; + } int index = fChildProcessors.count(); fChildProcessors.push_back(child.release()); diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp index 7767bf2..c60a94b 100644 --- a/src/gpu/GrPipeline.cpp +++ b/src/gpu/GrPipeline.cpp @@ -48,6 +48,9 @@ GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args, if (builder.getAllowSRGBInputs()) { pipeline->fFlags |= kAllowSRGBInputs_Flag; } + if (builder.getUsesDistanceVectorField()) { + pipeline->fFlags |= kUsesDistanceVectorField_Flag; + } if (args.fHasStencilClip) { pipeline->fFlags |= kHasStencilClip_Flag; } diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h index 5ec572d..1457dbc 100644 --- a/src/gpu/GrPipeline.h +++ b/src/gpu/GrPipeline.h @@ -160,6 +160,9 @@ public: bool getAllowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); } + bool usesDistanceVectorField() const { + return SkToBool(fFlags & kUsesDistanceVectorField_Flag); + } bool hasStencilClip() const { return SkToBool(fFlags & kHasStencilClip_Flag); } @@ -206,7 +209,8 @@ private: kSnapVertices_Flag = 0x2, kDisableOutputConversionToSRGB_Flag = 0x4, kAllowSRGBInputs_Flag = 0x8, - kHasStencilClip_Flag = 0x10 + kUsesDistanceVectorField_Flag = 0x10, + kHasStencilClip_Flag = 0x20, }; typedef GrPendingIOResource RenderTarget; diff --git a/src/gpu/GrPipelineBuilder.cpp b/src/gpu/GrPipelineBuilder.cpp index 60cbc62..864d6f1 100644 --- a/src/gpu/GrPipelineBuilder.cpp +++ b/src/gpu/GrPipelineBuilder.cpp @@ -41,6 +41,8 @@ GrPipelineBuilder::GrPipelineBuilder(const GrPaint& paint, bool useHWAA) paint.getDisableOutputConversionToSRGB()); this->setState(GrPipelineBuilder::kAllowSRGBInputs_Flag, paint.getAllowSRGBInputs()); + this->setState(GrPipelineBuilder::kUsesDistanceVectorField_Flag, + paint.usesDistanceVectorField()); } //////////////////////////////////////////////////////////////////////////////s diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h index dca7f36..0c33eb3 100644 --- a/src/gpu/GrPipelineBuilder.h +++ b/src/gpu/GrPipelineBuilder.h @@ -221,7 +221,13 @@ public: */ kAllowSRGBInputs_Flag = 0x08, - kLast_Flag = kAllowSRGBInputs_Flag, + /** + * Signals that one or more FPs need access to the distance vector field to the nearest + * edge + */ + kUsesDistanceVectorField_Flag = 0x10, + + kLast_Flag = kUsesDistanceVectorField_Flag, }; bool isHWAntialias() const { return SkToBool(fFlags & kHWAntialias_Flag); } @@ -231,6 +237,8 @@ public: return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag); } bool getAllowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); } + bool getUsesDistanceVectorField() const { + return SkToBool(fFlags & kUsesDistanceVectorField_Flag); } /** * Enable render state settings. diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h index 0d5280f..d27a6f3 100644 --- a/src/gpu/GrPrimitiveProcessor.h +++ b/src/gpu/GrPrimitiveProcessor.h @@ -221,6 +221,10 @@ public: return 0.0; } + /* Sub-class should override and return true if this primitive processor implements the distance + * vector field, a field of vectors to the nearest point in the edge of the shape. */ + virtual bool implementsDistanceVector() const { return false; } + protected: GrPrimitiveProcessor() : fVertexStride(0) {} diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp index 9533d5a..46945bd 100644 --- a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp +++ b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp @@ -107,7 +107,8 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu inputColor, childCoords, childTexSamplers, - childBufferSamplers); + childBufferSamplers, + args.fGpImplementsDistanceVector); this->childProcessor(childIndex)->emitCode(childArgs); fragBuilder->codeAppend("}\n"); diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.h b/src/gpu/glsl/GrGLSLFragmentProcessor.h index 43614f2..c6eb016 100644 --- a/src/gpu/glsl/GrGLSLFragmentProcessor.h +++ b/src/gpu/glsl/GrGLSLFragmentProcessor.h @@ -61,7 +61,8 @@ public: const char* inputColor, const GrGLSLTransformedCoordsArray& coords, const SamplerHandle* texSamplers, - const SamplerHandle* bufferSamplers) + const SamplerHandle* bufferSamplers, + bool gpImplementsDistanceVector) : fFragBuilder(fragBuilder) , fUniformHandler(uniformHandler) , fGLSLCaps(caps) @@ -70,7 +71,8 @@ public: , fInputColor(inputColor) , fCoords(coords) , fTexSamplers(texSamplers) - , fBufferSamplers(bufferSamplers) {} + , fBufferSamplers(bufferSamplers) + , fGpImplementsDistanceVector(gpImplementsDistanceVector){} GrGLSLFPFragmentBuilder* fFragBuilder; GrGLSLUniformHandler* fUniformHandler; const GrGLSLCaps* fGLSLCaps; @@ -80,6 +82,7 @@ public: const GrGLSLTransformedCoordsArray& fCoords; const SamplerHandle* fTexSamplers; const SamplerHandle* fBufferSamplers; + bool fGpImplementsDistanceVector; }; virtual void emitCode(EmitArgs&) = 0; diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp index 5d1ba51..e6ecf8c 100644 --- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp +++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp @@ -189,6 +189,10 @@ const char* GrGLSLFragmentShaderBuilder::fragmentPosition() { } } +const char* GrGLSLFragmentShaderBuilder::distanceVectorName() const { + return "fsDistanceVector"; +} + void GrGLSLFragmentShaderBuilder::appendOffsetToSample(const char* sampleIdx, Coordinates coords) { SkASSERT(fProgramBuilder->header().fSamplePatternKey); SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kSampleLocations_RequiredFeature); diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h index 614b04f..6845376 100644 --- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h +++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h @@ -96,6 +96,10 @@ public: */ virtual void maskSampleCoverage(const char* mask, bool invert = false) = 0; + /** Returns a variable name that represents a vector to the nearest edge of the shape, in source + space coordinates. */ + virtual const char* distanceVectorName() const = 0; + /** * Fragment procs with child procs should call these functions before/after calling emitCode * on a child proc. @@ -166,6 +170,7 @@ public: virtual SkString ensureFSCoords2D(const GrGLSLTransformedCoordsArray& coords, int index) override; const char* fragmentPosition() override; + const char* distanceVectorName() const override; // GrGLSLFPFragmentBuilder interface. void appendOffsetToSample(const char* sampleIdx, Coordinates) override; @@ -235,6 +240,7 @@ private: bool fHasSecondaryOutput; uint8_t fUsedSampleOffsetArrays; bool fHasInitializedSampleMask; + SkString fDistanceVectorOutput; #ifdef SK_DEBUG // some state to verify shaders and effects are consistent, this is reset between effects by diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.h b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h index d726027..a940996 100644 --- a/src/gpu/glsl/GrGLSLPrimitiveProcessor.h +++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h @@ -42,6 +42,7 @@ public: const GrPrimitiveProcessor& gp, const char* outputColor, const char* outputCoverage, + const char* distanceVectorName, const SamplerHandle* texSamplers, const SamplerHandle* bufferSamplers, const TransformsIn& transformsIn, @@ -54,6 +55,7 @@ public: , fGP(gp) , fOutputColor(outputColor) , fOutputCoverage(outputCoverage) + , fDistanceVectorName(distanceVectorName) , fTexSamplers(texSamplers) , fBufferSamplers(bufferSamplers) , fTransformsIn(transformsIn) @@ -66,6 +68,7 @@ public: const GrPrimitiveProcessor& fGP; const char* fOutputColor; const char* fOutputCoverage; + const char* fDistanceVectorName; const SamplerHandle* fTexSamplers; const SamplerHandle* fBufferSamplers; const TransformsIn& fTransformsIn; @@ -78,7 +81,6 @@ public: */ virtual void emitCode(EmitArgs&) = 0; - /** A GrGLSLPrimitiveProcessor instance can be reused with any GrGLSLPrimitiveProcessor that produces the same stage key; this function reads data from a GrGLSLPrimitiveProcessor and uploads any uniform variables required by the shaders created in emitCode(). The diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp index 64bc064..1f28f19 100644 --- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp +++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp @@ -87,6 +87,13 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr this->nameExpression(outputColor, "outputColor"); this->nameExpression(outputCoverage, "outputCoverage"); + const char* distanceVectorName = nullptr; + if (this->fPipeline.usesDistanceVectorField() && proc.implementsDistanceVector()) { + distanceVectorName = fFS.distanceVectorName(); + fFS.codeAppend( "// Un-normalized vector to the closed geometric edge (in source space)\n"); + fFS.codeAppendf("vec2 %s;", distanceVectorName); + } + // Enclose custom code in a block to avoid namespace conflicts SkString openBrace; openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); @@ -108,6 +115,7 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr proc, outputColor->c_str(), outputCoverage->c_str(), + distanceVectorName, texSamplers.begin(), bufferSamplers.begin(), fCoordTransforms, @@ -161,7 +169,9 @@ void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp, input.isOnes() ? nullptr : input.c_str(), fOutCoords[index], texSamplers.begin(), - bufferSamplers.begin()); + bufferSamplers.begin(), + this->primitiveProcessor().implementsDistanceVector()); + fragProc->emitCode(args); // We have to check that effects and the code they emit are consistent, ie if an effect