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 Committed: https://skia.googlesource.com/skia/+/4ef6dfa7089c092c67b0d5ec34e89c1e319af196 Review-Url: https://codereview.chromium.org/2114993002
This commit is contained in:
parent
6be452c800
commit
9b03e7b29d
@ -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',
|
||||
|
@ -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',
|
||||
|
@ -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;
|
||||
|
||||
|
@ -77,6 +77,11 @@ public:
|
||||
void setAllowSRGBInputs(bool allowSRGBInputs) { fAllowSRGBInputs = allowSRGBInputs; }
|
||||
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<GrFragmentProcessor> fp) {
|
||||
SkASSERT(fp);
|
||||
fUsesDistanceVectorField |= fp->usesDistanceVectorField();
|
||||
fColorFragmentProcessors.push_back(std::move(fp));
|
||||
}
|
||||
|
||||
@ -109,6 +115,7 @@ public:
|
||||
*/
|
||||
void addCoverageFragmentProcessor(sk_sp<GrFragmentProcessor> 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;
|
||||
};
|
||||
|
@ -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<NormalBevelFP>();
|
||||
|
||||
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<NormalBevelFP>();
|
||||
|
||||
if (fPrevWidth != normalBevelFP.fWidth) {
|
||||
|
@ -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<NormalFlatFP>();
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -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<NormalMapFP>();
|
||||
}
|
||||
|
||||
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<NormalMapFP>();
|
||||
|
||||
const SkMatrix& invCTM = normalMapFP.invCTM();
|
||||
|
@ -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.
|
||||
|
57
src/core/SkNormalSourcePriv.h
Normal file
57
src/core/SkNormalSourcePriv.h
Normal file
@ -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
|
@ -106,6 +106,9 @@ int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child
|
||||
if (child->usesLocalCoords()) {
|
||||
fUsesLocalCoords = true;
|
||||
}
|
||||
if (child->usesDistanceVectorField()) {
|
||||
fUsesDistanceVectorField = true;
|
||||
}
|
||||
|
||||
int index = fChildProcessors.count();
|
||||
fChildProcessors.push_back(child.release());
|
||||
|
@ -16,6 +16,7 @@ GrPaint::GrPaint()
|
||||
: fAntiAlias(false)
|
||||
, fDisableOutputConversionToSRGB(false)
|
||||
, fAllowSRGBInputs(false)
|
||||
, fUsesDistanceVectorField(false)
|
||||
, fColor(GrColor4f::FromGrColor(GrColor_WHITE)) {}
|
||||
|
||||
void GrPaint::setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<GrRenderTarget, kWrite_GrIOType> RenderTarget;
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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) {}
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user