aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2017-01-26 17:35:06 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-01-27 14:56:48 +0000
commit85eb4226a4cd8c10a0e3f3ba2f3a60efbb2dd61b (patch)
tree0f740e811d6360b4c5ae059e6a80431e8567ee43 /src
parentbcda1f07d5e1b8d080e0134a24c5bc1707ef3985 (diff)
Start of rewrite of GrFragmentProcessor optimizations.
This adds a replacement for computeInvariantOutput buts does not use it yet. The replacement allows for three types of optimizations: * known input color -> known output color for GrFP elimination * tracking of whether all color processors modulate their input for the "tweak alpha" optimziation * opaqueness tracking This loses some of the generality of computInvariantOutput. It does not track the known output status of individual color components (other than opaque alpha). It does not track whether GrFragmentProcessors read their input color. It doesn't allow a processor that will receive non-constant output to advertise that it produces a constant output. These could probably be added back in the unlikely case that they prove valuable. Unlike computeInvariantOutput the optimizations are decided at instantiation time and constant colors are expressed as GrColor4f rather than GrColor. Change-Id: I684d3f9050693dde2d28154fa695e049ed8cf61a Reviewed-on: https://skia-review.googlesource.com/7481 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/core/SkColorMatrixFilterRowMajor255.cpp5
-rw-r--r--src/core/SkLightingShader.cpp6
-rw-r--r--src/core/SkNormalBevelSource.cpp11
-rw-r--r--src/core/SkNormalFlatSource.cpp15
-rw-r--r--src/core/SkNormalMapSource.cpp4
-rw-r--r--src/effects/GrAlphaThresholdFragmentProcessor.cpp29
-rw-r--r--src/effects/GrAlphaThresholdFragmentProcessor.h2
-rw-r--r--src/effects/GrCircleBlurFragmentProcessor.cpp9
-rw-r--r--src/effects/SkArithmeticImageFilter.cpp8
-rw-r--r--src/effects/SkBlurMaskFilter.cpp20
-rw-r--r--src/effects/SkDisplacementMapEffect.cpp38
-rw-r--r--src/effects/SkGaussianEdgeShader.cpp6
-rw-r--r--src/effects/SkLightingImageFilter.cpp15
-rw-r--r--src/effects/SkLumaColorFilter.cpp10
-rw-r--r--src/effects/SkMagnifierImageFilter.cpp18
-rw-r--r--src/effects/SkMorphologyImageFilter.cpp14
-rw-r--r--src/effects/SkOverdrawColorFilter.cpp6
-rw-r--r--src/effects/SkPerlinNoiseShader.cpp18
-rw-r--r--src/effects/SkRRectsGaussianEdgeMaskFilter.cpp4
-rw-r--r--src/effects/SkTableColorFilter.cpp9
-rw-r--r--src/effects/gradients/SkGradientShader.cpp8
-rw-r--r--src/effects/gradients/SkGradientShaderPriv.h6
-rw-r--r--src/effects/gradients/SkLinearGradient.cpp3
-rw-r--r--src/effects/gradients/SkRadialGradient.cpp3
-rw-r--r--src/effects/gradients/SkSweepGradient.cpp3
-rw-r--r--src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp22
-rwxr-xr-xsrc/effects/shadows/SkAmbientShadowMaskFilter.cpp6
-rw-r--r--src/gpu/GrFragmentProcessor.cpp79
-rw-r--r--src/gpu/SkGrPriv.h18
-rw-r--r--src/gpu/effects/Gr1DKernelEffect.h12
-rw-r--r--src/gpu/effects/GrBicubicEffect.cpp18
-rw-r--r--src/gpu/effects/GrConfigConversionEffect.cpp8
-rw-r--r--src/gpu/effects/GrConfigConversionEffect.h1
-rw-r--r--src/gpu/effects/GrConstColorProcessor.cpp13
-rw-r--r--src/gpu/effects/GrConvexPolyEffect.cpp5
-rw-r--r--src/gpu/effects/GrDitherEffect.cpp4
-rw-r--r--src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp3
-rw-r--r--src/gpu/effects/GrMatrixConvolutionEffect.cpp14
-rw-r--r--src/gpu/effects/GrOvalEffect.cpp14
-rw-r--r--src/gpu/effects/GrRRectEffect.cpp14
-rw-r--r--src/gpu/effects/GrSRGBEffect.cpp24
-rw-r--r--src/gpu/effects/GrSRGBEffect.h1
-rw-r--r--src/gpu/effects/GrSimpleTextureEffect.h54
-rw-r--r--src/gpu/effects/GrSingleTextureEffect.cpp66
-rw-r--r--src/gpu/effects/GrSingleTextureEffect.h36
-rw-r--r--src/gpu/effects/GrTextureDomain.cpp18
-rw-r--r--src/gpu/effects/GrTextureDomain.h2
-rw-r--r--src/gpu/effects/GrXfermodeFragmentProcessor.cpp56
-rw-r--r--src/gpu/effects/GrYUVEffect.cpp30
49 files changed, 532 insertions, 256 deletions
diff --git a/src/core/SkColorMatrixFilterRowMajor255.cpp b/src/core/SkColorMatrixFilterRowMajor255.cpp
index 2bcc79e4cc..167fd21b38 100644
--- a/src/core/SkColorMatrixFilterRowMajor255.cpp
+++ b/src/core/SkColorMatrixFilterRowMajor255.cpp
@@ -345,9 +345,10 @@ public:
typedef GrGLSLFragmentProcessor INHERITED;
};
-
private:
- ColorMatrixEffect(const SkScalar matrix[20]) {
+ // We could implement the constant input->constant output optimization but haven't. Other
+ // optimizations would be matrix-dependent.
+ ColorMatrixEffect(const SkScalar matrix[20]) : INHERITED(kNone_OptimizationFlags) {
memcpy(fMatrix, matrix, sizeof(SkScalar) * 20);
this->initClassID<ColorMatrixEffect>();
}
diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp
index bb2828a13e..4ed0057682 100644
--- a/src/core/SkLightingShader.cpp
+++ b/src/core/SkLightingShader.cpp
@@ -117,8 +117,8 @@ private:
// premul'd.
class LightingFP : public GrFragmentProcessor {
public:
- LightingFP(sk_sp<GrFragmentProcessor> normalFP, sk_sp<SkLights> lights) {
-
+ LightingFP(sk_sp<GrFragmentProcessor> normalFP, sk_sp<SkLights> lights)
+ : INHERITED(kPreservesOpaqueInput_OptimizationFlag) {
// fuse all ambient lights into a single one
fAmbientColor = lights->ambientLightColor();
for (int i = 0; i < lights->numLights(); ++i) {
@@ -263,6 +263,8 @@ private:
SkTArray<SkLights::Light> fDirectionalLights;
SkColor3f fAmbientColor;
+
+ typedef GrFragmentProcessor INHERITED;
};
////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkNormalBevelSource.cpp b/src/core/SkNormalBevelSource.cpp
index bcdb999c15..5d49253b01 100644
--- a/src/core/SkNormalBevelSource.cpp
+++ b/src/core/SkNormalBevelSource.cpp
@@ -30,12 +30,13 @@
class NormalBevelFP : public GrFragmentProcessor {
public:
NormalBevelFP(SkNormalSource::BevelType bevelType, SkScalar bevelWidth, SkScalar bevelHeight)
- : fBevelType(bevelType)
- , fBevelWidth(bevelWidth)
- , fBevelHeight(bevelHeight) {
+ : INHERITED(kNone_OptimizationFlags)
+ , fBevelType(bevelType)
+ , fBevelWidth(bevelWidth)
+ , fBevelHeight(bevelHeight) {
this->initClassID<NormalBevelFP>();
- fUsesDistanceVectorField = true;
+ this->setWillUseDistanceVectorField();
}
class GLSLNormalBevelFP : public GLSLNormalFP {
@@ -239,6 +240,8 @@ private:
SkNormalSource::BevelType fBevelType;
SkScalar fBevelWidth;
SkScalar fBevelHeight;
+
+ typedef GrFragmentProcessor INHERITED;
};
sk_sp<GrFragmentProcessor> SkNormalBevelSourceImpl::asFragmentProcessor(
diff --git a/src/core/SkNormalFlatSource.cpp b/src/core/SkNormalFlatSource.cpp
index 4fca57c1f3..b4ed977285 100644
--- a/src/core/SkNormalFlatSource.cpp
+++ b/src/core/SkNormalFlatSource.cpp
@@ -20,7 +20,7 @@
class NormalFlatFP : public GrFragmentProcessor {
public:
- NormalFlatFP() {
+ NormalFlatFP() : INHERITED(kConstantOutputForConstantInput_OptimizationFlag) {
this->initClassID<NormalFlatFP>();
}
@@ -43,20 +43,23 @@ public:
const GrProcessor& proc) override {}
};
+ const char* name() const override { return "NormalFlatFP"; }
+
+private:
void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
GLSLNormalFlatFP::GenKey(*this, caps, b);
}
-
- const char* name() const override { return "NormalFlatFP"; }
-
void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
inout->setToUnknown();
}
-
-private:
+ GrColor4f constantOutputForConstantInput(GrColor4f) const override {
+ return GrColor4f(0, 0, 1, 0);
+ }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLNormalFlatFP; }
bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
+
+ typedef GrFragmentProcessor INHERITED;
};
sk_sp<GrFragmentProcessor> SkNormalFlatSourceImpl::asFragmentProcessor(
diff --git a/src/core/SkNormalMapSource.cpp b/src/core/SkNormalMapSource.cpp
index 71e5565ac8..3a9f9cf76f 100644
--- a/src/core/SkNormalMapSource.cpp
+++ b/src/core/SkNormalMapSource.cpp
@@ -26,7 +26,7 @@
class NormalMapFP : public GrFragmentProcessor {
public:
NormalMapFP(sk_sp<GrFragmentProcessor> mapFP, const SkMatrix& invCTM)
- : fInvCTM(invCTM) {
+ : INHERITED(kNone_OptimizationFlags), fInvCTM(invCTM) {
this->registerChildProcessor(mapFP);
this->initClassID<NormalMapFP>();
@@ -117,6 +117,8 @@ private:
}
SkMatrix fInvCTM;
+
+ typedef GrFragmentProcessor INHERITED;
};
sk_sp<GrFragmentProcessor> SkNormalMapSourceImpl::asFragmentProcessor(
diff --git a/src/effects/GrAlphaThresholdFragmentProcessor.cpp b/src/effects/GrAlphaThresholdFragmentProcessor.cpp
index a259607444..8f9e45dc2b 100644
--- a/src/effects/GrAlphaThresholdFragmentProcessor.cpp
+++ b/src/effects/GrAlphaThresholdFragmentProcessor.cpp
@@ -32,6 +32,14 @@ sk_sp<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::Make(
bounds));
}
+inline GrFragmentProcessor::OptimizationFlags GrAlphaThresholdFragmentProcessor::OptFlags(float outerThreshold) {
+ if (outerThreshold >= 1.f) {
+ return kPreservesOpaqueInput_OptimizationFlag | kModulatesInput_OptimizationFlag;
+ } else {
+ return kModulatesInput_OptimizationFlag;
+ }
+}
+
GrAlphaThresholdFragmentProcessor::GrAlphaThresholdFragmentProcessor(
GrTexture* texture,
sk_sp<GrColorSpaceXform> colorSpaceXform,
@@ -39,16 +47,17 @@ GrAlphaThresholdFragmentProcessor::GrAlphaThresholdFragmentProcessor(
float innerThreshold,
float outerThreshold,
const SkIRect& bounds)
- : fInnerThreshold(innerThreshold)
- , fOuterThreshold(outerThreshold)
- , fImageCoordTransform(SkMatrix::I(), texture, GrSamplerParams::kNone_FilterMode)
- , fImageTextureSampler(texture)
- , fColorSpaceXform(std::move(colorSpaceXform))
- , fMaskCoordTransform(SkMatrix::MakeTrans(SkIntToScalar(-bounds.x()),
- SkIntToScalar(-bounds.y())),
- maskTexture,
- GrSamplerParams::kNone_FilterMode)
- , fMaskTextureSampler(maskTexture) {
+ : INHERITED(OptFlags(outerThreshold))
+ , fInnerThreshold(innerThreshold)
+ , fOuterThreshold(outerThreshold)
+ , fImageCoordTransform(SkMatrix::I(), texture, GrSamplerParams::kNone_FilterMode)
+ , fImageTextureSampler(texture)
+ , fColorSpaceXform(std::move(colorSpaceXform))
+ , fMaskCoordTransform(
+ SkMatrix::MakeTrans(SkIntToScalar(-bounds.x()), SkIntToScalar(-bounds.y())),
+ maskTexture,
+ GrSamplerParams::kNone_FilterMode)
+ , fMaskTextureSampler(maskTexture) {
this->initClassID<GrAlphaThresholdFragmentProcessor>();
this->addCoordTransform(&fImageCoordTransform);
this->addTextureSampler(&fImageTextureSampler);
diff --git a/src/effects/GrAlphaThresholdFragmentProcessor.h b/src/effects/GrAlphaThresholdFragmentProcessor.h
index f7a2491aee..f2c14c64bc 100644
--- a/src/effects/GrAlphaThresholdFragmentProcessor.h
+++ b/src/effects/GrAlphaThresholdFragmentProcessor.h
@@ -35,6 +35,8 @@ public:
GrColorSpaceXform* colorSpaceXform() const { return fColorSpaceXform.get(); }
private:
+ static OptimizationFlags OptFlags(float outerThreshold);
+
GrAlphaThresholdFragmentProcessor(GrTexture* texture,
sk_sp<GrColorSpaceXform> colorSpaceXform,
GrTexture* maskTexture,
diff --git a/src/effects/GrCircleBlurFragmentProcessor.cpp b/src/effects/GrCircleBlurFragmentProcessor.cpp
index d3eb325b34..91d17d6e6c 100644
--- a/src/effects/GrCircleBlurFragmentProcessor.cpp
+++ b/src/effects/GrCircleBlurFragmentProcessor.cpp
@@ -88,10 +88,11 @@ GrCircleBlurFragmentProcessor::GrCircleBlurFragmentProcessor(const SkRect& circl
float textureRadius,
float solidRadius,
GrTexture* blurProfile)
- : fCircle(circle)
- , fSolidRadius(solidRadius)
- , fTextureRadius(textureRadius)
- , fBlurProfileSampler(blurProfile, GrSamplerParams::kBilerp_FilterMode) {
+ : INHERITED(kModulatesInput_OptimizationFlag)
+ , fCircle(circle)
+ , fSolidRadius(solidRadius)
+ , fTextureRadius(textureRadius)
+ , fBlurProfileSampler(blurProfile, GrSamplerParams::kBilerp_FilterMode) {
this->initClassID<GrCircleBlurFragmentProcessor>();
this->addTextureSampler(&fBlurProfileSampler);
}
diff --git a/src/effects/SkArithmeticImageFilter.cpp b/src/effects/SkArithmeticImageFilter.cpp
index 8d80984bdf..a9a232554f 100644
--- a/src/effects/SkArithmeticImageFilter.cpp
+++ b/src/effects/SkArithmeticImageFilter.cpp
@@ -290,9 +290,15 @@ private:
inout->setToUnknown();
}
+ // This could implement the const input -> const output optimization but it's unlikely to help.
ArithmeticFP(float k1, float k2, float k3, float k4, bool enforcePMColor,
sk_sp<GrFragmentProcessor> dst)
- : fK1(k1), fK2(k2), fK3(k3), fK4(k4), fEnforcePMColor(enforcePMColor) {
+ : INHERITED(kNone_OptimizationFlags)
+ , fK1(k1)
+ , fK2(k2)
+ , fK3(k3)
+ , fK4(k4)
+ , fEnforcePMColor(enforcePMColor) {
this->initClassID<ArithmeticFP>();
SkASSERT(dst);
SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(dst));
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index b53fc41dea..bf544077df 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -974,12 +974,13 @@ GrTexture* GrRectBlurEffect::CreateBlurProfileTexture(GrTextureProvider* texture
return blurProfile;
}
-GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blurProfile,
+GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture* blurProfile,
GrSLPrecision precision)
- : fRect(rect)
- , fSigma(sigma)
- , fBlurProfileSampler(blurProfile)
- , fPrecision(precision) {
+ : INHERITED(kModulatesInput_OptimizationFlag)
+ , fRect(rect)
+ , fSigma(sigma)
+ , fBlurProfileSampler(blurProfile)
+ , fPrecision(precision) {
this->initClassID<GrRectBlurEffect>();
this->addTextureSampler(&fBlurProfileSampler);
}
@@ -1206,10 +1207,11 @@ void GrRRectBlurEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const
inout->mulByUnknownSingleComponent();
}
-GrRRectBlurEffect::GrRRectBlurEffect(float sigma, const SkRRect& rrect, GrTexture *ninePatchTexture)
- : fRRect(rrect),
- fSigma(sigma),
- fNinePatchSampler(ninePatchTexture) {
+GrRRectBlurEffect::GrRRectBlurEffect(float sigma, const SkRRect& rrect, GrTexture* ninePatchTexture)
+ : INHERITED(kModulatesInput_OptimizationFlag)
+ , fRRect(rrect)
+ , fSigma(sigma)
+ , fNinePatchSampler(ninePatchTexture) {
this->initClassID<GrRRectBlurEffect>();
this->addTextureSampler(&fNinePatchSampler);
}
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index d838e1e347..cee47f4f3f 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -487,24 +487,26 @@ void GrDisplacementMapEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
}
GrDisplacementMapEffect::GrDisplacementMapEffect(
- SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
- SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
- const SkVector& scale,
- GrTexture* displacement,
- const SkMatrix& offsetMatrix,
- GrTexture* color,
- sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkISize& colorDimensions)
- : fDisplacementTransform(offsetMatrix, displacement, GrSamplerParams::kNone_FilterMode)
- , fDisplacementSampler(displacement)
- , fColorTransform(color, GrSamplerParams::kNone_FilterMode)
- , fDomain(color, GrTextureDomain::MakeTexelDomain(SkIRect::MakeSize(colorDimensions)),
- GrTextureDomain::kDecal_Mode)
- , fColorSampler(color)
- , fColorSpaceXform(std::move(colorSpaceXform))
- , fXChannelSelector(xChannelSelector)
- , fYChannelSelector(yChannelSelector)
- , fScale(scale) {
+ SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
+ SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
+ const SkVector& scale,
+ GrTexture* displacement,
+ const SkMatrix& offsetMatrix,
+ GrTexture* color,
+ sk_sp<GrColorSpaceXform> colorSpaceXform,
+ const SkISize& colorDimensions)
+ : INHERITED(GrPixelConfigIsOpaque(color->config()) ? kPreservesOpaqueInput_OptimizationFlag
+ : kNone_OptimizationFlags)
+ , fDisplacementTransform(offsetMatrix, displacement, GrSamplerParams::kNone_FilterMode)
+ , fDisplacementSampler(displacement)
+ , fColorTransform(color, GrSamplerParams::kNone_FilterMode)
+ , fDomain(color, GrTextureDomain::MakeTexelDomain(SkIRect::MakeSize(colorDimensions)),
+ GrTextureDomain::kDecal_Mode)
+ , fColorSampler(color)
+ , fColorSpaceXform(std::move(colorSpaceXform))
+ , fXChannelSelector(xChannelSelector)
+ , fYChannelSelector(yChannelSelector)
+ , fScale(scale) {
this->initClassID<GrDisplacementMapEffect>();
this->addCoordTransform(&fDisplacementTransform);
this->addTextureSampler(&fDisplacementSampler);
diff --git a/src/effects/SkGaussianEdgeShader.cpp b/src/effects/SkGaussianEdgeShader.cpp
index 7405fd14d9..5bd7dca124 100644
--- a/src/effects/SkGaussianEdgeShader.cpp
+++ b/src/effects/SkGaussianEdgeShader.cpp
@@ -63,11 +63,11 @@ private:
class GaussianEdgeFP : public GrFragmentProcessor {
public:
- GaussianEdgeFP() {
+ GaussianEdgeFP() : INHERITED(kNone_OptimizationFlags) {
this->initClassID<GaussianEdgeFP>();
// enable output of distance information for shape
- fUsesDistanceVectorField = true;
+ this->setWillUseDistanceVectorField();
}
class GLSLGaussianEdgeFP : public GrGLSLFragmentProcessor {
@@ -123,6 +123,8 @@ private:
}
bool onIsEqual(const GrFragmentProcessor& proc) const override { return true; }
+
+ typedef GrFragmentProcessor INHERITED;
};
////////////////////////////////////////////////////////////////////////////
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index da4dcb8bdf..3a03a1701c 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -1625,7 +1625,7 @@ SkString emitNormalFunc(BoundaryMode mode,
}
-class GrGLLightingEffect : public GrGLSLFragmentProcessor {
+class GrGLLightingEffect : public GrGLSLFragmentProcessor {
public:
GrGLLightingEffect() : fLight(nullptr) { }
virtual ~GrGLLightingEffect() { delete fLight; }
@@ -1702,12 +1702,13 @@ GrLightingEffect::GrLightingEffect(GrTexture* texture,
const SkMatrix& matrix,
BoundaryMode boundaryMode,
const SkIRect* srcBounds)
- : INHERITED(texture, nullptr, SkMatrix::I())
- , fLight(light)
- , fSurfaceScale(surfaceScale)
- , fFilterMatrix(matrix)
- , fBoundaryMode(boundaryMode)
- , fDomain(create_domain(texture, srcBounds, GrTextureDomain::kDecal_Mode)) {
+ // Perhaps this could advertise the opaque or modulating optimizations?
+ : INHERITED(texture, nullptr, SkMatrix::I(), kNone_OptimizationFlags)
+ , fLight(light)
+ , fSurfaceScale(surfaceScale)
+ , fFilterMatrix(matrix)
+ , fBoundaryMode(boundaryMode)
+ , fDomain(create_domain(texture, srcBounds, GrTextureDomain::kDecal_Mode)) {
fLight->ref();
}
diff --git a/src/effects/SkLumaColorFilter.cpp b/src/effects/SkLumaColorFilter.cpp
index a9516af63d..1792437e34 100644
--- a/src/effects/SkLumaColorFilter.cpp
+++ b/src/effects/SkLumaColorFilter.cpp
@@ -98,7 +98,7 @@ public:
};
private:
- LumaColorFilterEffect() {
+ LumaColorFilterEffect() : INHERITED(kConstantOutputForConstantInput_OptimizationFlag) {
this->initClassID<LumaColorFilterEffect>();
}
@@ -117,6 +117,14 @@ private:
// The output is always black. The alpha value for the color passed in is arbitrary.
inout->setToOther(kRGB_GrColorComponentFlags, GrColorPackRGBA(0, 0, 0, 0));
}
+ GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
+ float luma = SK_ITU_BT709_LUM_COEFF_R * input.fRGBA[0] +
+ SK_ITU_BT709_LUM_COEFF_G * input.fRGBA[1] +
+ SK_ITU_BT709_LUM_COEFF_B * input.fRGBA[2];
+ return GrColor4f(0, 0, 0, luma);
+ }
+
+ typedef GrFragmentProcessor INHERITED;
};
sk_sp<GrFragmentProcessor> SkLumaColorFilter::asFragmentProcessor(GrContext*, SkColorSpace*) const {
diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp
index c8b32aee70..49f4fdddc3 100644
--- a/src/effects/SkMagnifierImageFilter.cpp
+++ b/src/effects/SkMagnifierImageFilter.cpp
@@ -27,7 +27,6 @@
#include "../private/GrGLSL.h"
class GrMagnifierEffect : public GrSingleTextureEffect {
-
public:
static sk_sp<GrFragmentProcessor> Make(GrTexture* texture,
sk_sp<GrColorSpaceXform> colorSpaceXform,
@@ -71,14 +70,15 @@ private:
float yInvZoom,
float xInvInset,
float yInvInset)
- : INHERITED(texture, std::move(colorSpaceXform), SkMatrix::I())
- , fBounds(bounds)
- , fXOffset(xOffset)
- , fYOffset(yOffset)
- , fXInvZoom(xInvZoom)
- , fYInvZoom(yInvZoom)
- , fXInvInset(xInvInset)
- , fYInvInset(yInvInset) {
+ : INHERITED(texture, std::move(colorSpaceXform), SkMatrix::I(),
+ ModulationFlags(texture->config()))
+ , fBounds(bounds)
+ , fXOffset(xOffset)
+ , fYOffset(yOffset)
+ , fXInvZoom(xInvZoom)
+ , fYInvZoom(yInvZoom)
+ , fXInvInset(xInvInset)
+ , fYInvInset(yInvInset) {
this->initClassID<GrMagnifierEffect>();
}
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index 6e2a80507f..febde203d5 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -140,9 +140,7 @@ void SkDilateImageFilter::toString(SkString* str) const {
* color.
*/
class GrMorphologyEffect : public Gr1DKernelEffect {
-
public:
-
enum MorphologyType {
kErode_MorphologyType,
kDilate_MorphologyType,
@@ -327,9 +325,9 @@ GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture,
Direction direction,
int radius,
MorphologyType type)
- : INHERITED(texture, direction, radius)
- , fType(type)
- , fUseRange(false) {
+ : INHERITED(texture, direction, radius, ModulationFlags(texture->config()))
+ , fType(type)
+ , fUseRange(false) {
this->initClassID<GrMorphologyEffect>();
}
@@ -338,9 +336,9 @@ GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture,
int radius,
MorphologyType type,
const float range[2])
- : INHERITED(texture, direction, radius)
- , fType(type)
- , fUseRange(true) {
+ : INHERITED(texture, direction, radius, ModulationFlags(texture->config()))
+ , fType(type)
+ , fUseRange(true) {
this->initClassID<GrMorphologyEffect>();
fRange[0] = range[0];
fRange[1] = range[1];
diff --git a/src/effects/SkOverdrawColorFilter.cpp b/src/effects/SkOverdrawColorFilter.cpp
index dea4f8b6de..243ef77cd0 100644
--- a/src/effects/SkOverdrawColorFilter.cpp
+++ b/src/effects/SkOverdrawColorFilter.cpp
@@ -59,7 +59,6 @@ public:
static sk_sp<GrFragmentProcessor> Make(const SkPMColor* colors);
const char* name() const override { return "Overdraw"; }
-
private:
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
@@ -105,7 +104,10 @@ sk_sp<GrFragmentProcessor> OverdrawFragmentProcessor::Make(const SkPMColor* colo
return sk_sp<OverdrawFragmentProcessor>(new OverdrawFragmentProcessor(grColors));
}
-OverdrawFragmentProcessor::OverdrawFragmentProcessor(const GrColor4f* colors) {
+// This could implement the constant input -> constant output optimization, but we don't really
+// care given how this is used.
+OverdrawFragmentProcessor::OverdrawFragmentProcessor(const GrColor4f* colors)
+ : INHERITED(kNone_OptimizationFlags) {
this->initClassID<OverdrawFragmentProcessor>();
memcpy(fColors, colors, SkOverdrawColorFilter::kNumColors * sizeof(GrColor4f));
}
diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp
index 3798a407ac..450fcaa4ef 100644
--- a/src/effects/SkPerlinNoiseShader.cpp
+++ b/src/effects/SkPerlinNoiseShader.cpp
@@ -538,18 +538,18 @@ private:
inout->setToUnknown();
}
- GrPerlinNoiseEffect(SkPerlinNoiseShader::Type type,
- int numOctaves, bool stitchTiles,
+ GrPerlinNoiseEffect(SkPerlinNoiseShader::Type type, int numOctaves, bool stitchTiles,
SkPerlinNoiseShader::PaintingData* paintingData,
GrTexture* permutationsTexture, GrTexture* noiseTexture,
const SkMatrix& matrix)
- : fType(type)
- , fCoordTransform(matrix)
- , fNumOctaves(numOctaves)
- , fStitchTiles(stitchTiles)
- , fPermutationsSampler(permutationsTexture)
- , fNoiseSampler(noiseTexture)
- , fPaintingData(paintingData) {
+ : INHERITED(kNone_OptimizationFlags)
+ , fType(type)
+ , fCoordTransform(matrix)
+ , fNumOctaves(numOctaves)
+ , fStitchTiles(stitchTiles)
+ , fPermutationsSampler(permutationsTexture)
+ , fNoiseSampler(noiseTexture)
+ , fPaintingData(paintingData) {
this->initClassID<GrPerlinNoiseEffect>();
this->addTextureSampler(&fPermutationsSampler);
this->addTextureSampler(&fNoiseSampler);
diff --git a/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp b/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp
index 5da3ed1eb1..223887bab9 100644
--- a/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp
+++ b/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp
@@ -207,9 +207,7 @@ public:
};
RRectsGaussianEdgeFP(const SkRRect& first, const SkRRect& second, SkScalar radius)
- : fFirst(first)
- , fSecond(second)
- , fRadius(radius) {
+ : INHERITED(kNone_OptimizationFlags), fFirst(first), fSecond(second), fRadius(radius) {
this->initClassID<RRectsGaussianEdgeFP>();
fFirstMode = ComputeMode(fFirst);
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index 1fd4c90eed..9198460c66 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -512,10 +512,11 @@ sk_sp<GrFragmentProcessor> ColorTableEffect::Make(GrContext* context, SkBitmap b
ColorTableEffect::ColorTableEffect(GrTexture* texture, GrTextureStripAtlas* atlas, int row,
unsigned flags)
- : fTextureSampler(texture)
- , fFlags(flags)
- , fAtlas(atlas)
- , fRow(row) {
+ : INHERITED(kNone_OptimizationFlags) // Not bothering with table-specific optimizations.
+ , fTextureSampler(texture)
+ , fFlags(flags)
+ , fAtlas(atlas)
+ , fRow(row) {
this->initClassID<ColorTableEffect>();
this->addTextureSampler(&fTextureSampler);
}
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index b1d3e13a46..9a3438efe0 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -1572,7 +1572,13 @@ void GrGradientEffect::GLSLProcessor::emitColor(GrGLSLFPFragmentBuilder* fragBui
/////////////////////////////////////////////////////////////////////
-GrGradientEffect::GrGradientEffect(const CreateArgs& args) {
+inline GrFragmentProcessor::OptimizationFlags GrGradientEffect::OptFlags(bool isOpaque) {
+ return isOpaque ? kPreservesOpaqueInput_OptimizationFlag | kModulatesInput_OptimizationFlag
+ : kModulatesInput_OptimizationFlag;
+}
+
+GrGradientEffect::GrGradientEffect(const CreateArgs& args, bool isOpaque)
+ : INHERITED(OptFlags(isOpaque)) {
const SkGradientShaderBase& shader(*args.fShader);
fIsOpaque = shader.isOpaque();
diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h
index 48ccbd50d0..6f46698eba 100644
--- a/src/effects/gradients/SkGradientShaderPriv.h
+++ b/src/effects/gradients/SkGradientShaderPriv.h
@@ -352,8 +352,6 @@ public:
class GLSLProcessor;
- GrGradientEffect(const CreateArgs&);
-
virtual ~GrGradientEffect();
bool useAtlas() const { return SkToBool(-1 != fRow); }
@@ -402,6 +400,8 @@ public:
}
protected:
+ GrGradientEffect(const CreateArgs&, bool isOpaque);
+
/** Helper struct that stores (and populates) parameters to construct a random gradient.
If fUseColors4f is true, then the SkColor4f factory should be called, with fColors4f and
fColorSpace. Otherwise, the SkColor factory should be called, with fColors. fColorCount
@@ -430,6 +430,8 @@ protected:
const GrCoordTransform& getCoordTransform() const { return fCoordTransform; }
private:
+ static OptimizationFlags OptFlags(bool isOpaque);
+
// If we're in legacy mode, then fColors will be populated. If we're gamma-correct, then
// fColors4f and fColorSpaceXform will be populated.
SkTDArray<SkColor> fColors;
diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp
index aab1ac787a..07418e8010 100644
--- a/src/effects/gradients/SkLinearGradient.cpp
+++ b/src/effects/gradients/SkLinearGradient.cpp
@@ -426,8 +426,7 @@ public:
const char* name() const override { return "Linear Gradient"; }
private:
- GrLinearGradient(const CreateArgs& args)
- : INHERITED(args) {
+ GrLinearGradient(const CreateArgs& args) : INHERITED(args, args.fShader->colorsAreOpaque()) {
this->initClassID<GrLinearGradient>();
}
diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp
index 887410aa96..4eb3e6d93a 100644
--- a/src/effects/gradients/SkRadialGradient.cpp
+++ b/src/effects/gradients/SkRadialGradient.cpp
@@ -256,8 +256,7 @@ public:
const char* name() const override { return "Radial Gradient"; }
private:
- GrRadialGradient(const CreateArgs& args)
- : INHERITED(args) {
+ GrRadialGradient(const CreateArgs& args) : INHERITED(args, args.fShader->colorsAreOpaque()) {
this->initClassID<GrRadialGradient>();
}
diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp
index 64778c3a54..7e93a21de4 100644
--- a/src/effects/gradients/SkSweepGradient.cpp
+++ b/src/effects/gradients/SkSweepGradient.cpp
@@ -138,8 +138,7 @@ public:
const char* name() const override { return "Sweep Gradient"; }
private:
- GrSweepGradient(const CreateArgs& args)
- : INHERITED(args) {
+ GrSweepGradient(const CreateArgs& args) : INHERITED(args, args.fShader->colorsAreOpaque()) {
this->initClassID<GrSweepGradient>();
}
diff --git a/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp b/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp
index 5f26dcdb13..75b1cf7090 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp
@@ -92,7 +92,7 @@ private:
}
Edge2PtConicalEffect(const CreateArgs& args)
- : INHERITED(args) {
+ : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */) {
const SkTwoPointConicalGradient& shader =
*static_cast<const SkTwoPointConicalGradient*>(args.fShader);
fCenterX1 = shader.getCenterX1();
@@ -398,10 +398,15 @@ private:
this->fIsFlipped == s.fIsFlipped);
}
+ static bool IsFlipped(const CreateArgs& args) {
+ // eww.
+ return static_cast<const SkTwoPointConicalGradient*>(args.fShader)->isFlippedGrad();
+ }
+
FocalOutside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
- : INHERITED(args)
- , fFocalX(focalX)
- , fIsFlipped(static_cast<const SkTwoPointConicalGradient*>(args.fShader)->isFlippedGrad()) {
+ : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */)
+ , fFocalX(focalX)
+ , fIsFlipped(IsFlipped(args)) {
this->initClassID<FocalOutside2PtConicalEffect>();
}
@@ -413,7 +418,7 @@ private:
typedef GrGradientEffect INHERITED;
};
-class FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
+class FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
: public GrGradientEffect::GLSLProcessor {
public:
GLSLFocalOutside2PtConicalProcessor(const GrProcessor&);
@@ -606,7 +611,7 @@ private:
}
FocalInside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
- : INHERITED(args), fFocalX(focalX) {
+ : INHERITED(args, args.fShader->colorsAreOpaque()), fFocalX(focalX) {
this->initClassID<FocalInside2PtConicalEffect>();
}
@@ -847,7 +852,7 @@ private:
}
CircleInside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
- : INHERITED(args), fInfo(info) {
+ : INHERITED(args, args.fShader->colorsAreOpaque()), fInfo(info) {
this->initClassID<CircleInside2PtConicalEffect>();
}
@@ -1064,7 +1069,8 @@ private:
}
CircleOutside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
- : INHERITED(args), fInfo(info) {
+ : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */)
+ , fInfo(info) {
this->initClassID<CircleOutside2PtConicalEffect>();
const SkTwoPointConicalGradient& shader =
*static_cast<const SkTwoPointConicalGradient*>(args.fShader);
diff --git a/src/effects/shadows/SkAmbientShadowMaskFilter.cpp b/src/effects/shadows/SkAmbientShadowMaskFilter.cpp
index d92a7b548c..e7d8d31302 100755
--- a/src/effects/shadows/SkAmbientShadowMaskFilter.cpp
+++ b/src/effects/shadows/SkAmbientShadowMaskFilter.cpp
@@ -140,9 +140,7 @@ void SkAmbientShadowMaskFilterImpl::flatten(SkWriteBuffer& buffer) const {
//
class ShadowEdgeFP : public GrFragmentProcessor {
public:
- ShadowEdgeFP() {
- this->initClassID<ShadowEdgeFP>();
- }
+ ShadowEdgeFP() : INHERITED(kNone_OptimizationFlags) { this->initClassID<ShadowEdgeFP>(); }
class GLSLShadowEdgeFP : public GrGLSLFragmentProcessor {
public:
@@ -179,6 +177,8 @@ private:
}
bool onIsEqual(const GrFragmentProcessor& proc) const override { return true; }
+
+ typedef GrFragmentProcessor INHERITED;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index 0ad144a3be..f294ac646d 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -58,7 +58,7 @@ GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
fCoordTransforms.push_back(transform);
- fUsesLocalCoords = true;
+ fFlags |= kUsesLocalCoords_Flag;
SkDEBUGCODE(transform->setInProcessor();)
}
@@ -66,10 +66,10 @@ int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child
this->combineRequiredFeatures(*child);
if (child->usesLocalCoords()) {
- fUsesLocalCoords = true;
+ fFlags |= kUsesLocalCoords_Flag;
}
if (child->usesDistanceVectorField()) {
- fUsesDistanceVectorField = true;
+ fFlags |= kUsesDistanceVectorField_Flag;
}
int index = fChildProcessors.count();
@@ -111,12 +111,13 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProc
class PremulInputFragmentProcessor : public GrFragmentProcessor {
public:
- PremulInputFragmentProcessor() {
+ PremulInputFragmentProcessor()
+ : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
+ kConstantOutputForConstantInput_OptimizationFlag) {
this->initClassID<PremulInputFragmentProcessor>();
}
const char* name() const override { return "PremultiplyInput"; }
-
private:
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
class GLFP : public GrGLSLFragmentProcessor {
@@ -139,6 +140,11 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProc
void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
inout->premulFourChannelColor();
}
+ GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
+ return input.premul();
+ }
+
+ typedef GrFragmentProcessor INHERITED;
};
if (!fp) {
return nullptr;
@@ -152,7 +158,8 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputUnpremulColor(
class PremulFragmentProcessor : public GrFragmentProcessor {
public:
- PremulFragmentProcessor(sk_sp<GrFragmentProcessor> processor) {
+ PremulFragmentProcessor(sk_sp<GrFragmentProcessor> processor)
+ : INHERITED(OptFlags(processor.get())) {
this->initClassID<PremulFragmentProcessor>();
this->registerChildProcessor(processor);
}
@@ -178,6 +185,16 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputUnpremulColor(
bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
+ static OptimizationFlags OptFlags(const GrFragmentProcessor* inner) {
+ OptimizationFlags flags = kNone_OptimizationFlags;
+ if (inner->preservesOpaqueInput()) {
+ flags |= kPreservesOpaqueInput_OptimizationFlag;
+ }
+ if (inner->hasConstantOutputForConstantInput()) {
+ flags |= kConstantOutputForConstantInput_OptimizationFlag;
+ }
+ return flags;
+ }
void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
// TODO: Add a helper to GrInvariantOutput that handles multiplying by color with flags?
if (!(inout->validFlags() & kA_GrColorComponentFlag)) {
@@ -210,6 +227,16 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputUnpremulColor(
}
inout->setToOther(commonFlags, color);
}
+ GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
+ GrColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
+ GrColor4f::OpaqueWhite());
+ return GrColor4f(input.fRGBA[3] * input.fRGBA[0] * childColor.fRGBA[0],
+ input.fRGBA[3] * input.fRGBA[1] * childColor.fRGBA[1],
+ input.fRGBA[3] * input.fRGBA[2] * childColor.fRGBA[2],
+ input.fRGBA[3] * childColor.fRGBA[3]);
+ }
+
+ typedef GrFragmentProcessor INHERITED;
};
if (!fp) {
return nullptr;
@@ -224,7 +251,7 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentPr
class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
public:
ReplaceInputFragmentProcessor(sk_sp<GrFragmentProcessor> child, GrColor4f color)
- : fColor(color) {
+ : INHERITED(OptFlags(child.get(), color)), fColor(color) {
this->initClassID<ReplaceInputFragmentProcessor>();
this->registerChildProcessor(std::move(child));
}
@@ -264,6 +291,18 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentPr
}
private:
+ static OptimizationFlags OptFlags(const GrFragmentProcessor* child, GrColor4f color) {
+ OptimizationFlags childFlags = child->optimizationFlags();
+ OptimizationFlags flags = kNone_OptimizationFlags;
+ if (childFlags & kConstantOutputForConstantInput_OptimizationFlag) {
+ flags |= kConstantOutputForConstantInput_OptimizationFlag;
+ }
+ if ((childFlags & kPreservesOpaqueInput_OptimizationFlag) && color.isOpaque()) {
+ flags |= kPreservesOpaqueInput_OptimizationFlag;
+ }
+ return flags;
+ }
+
void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override
{}
@@ -276,7 +315,13 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentPr
this->childProcessor(0).computeInvariantOutput(inout);
}
+ GrColor4f constantOutputForConstantInput(GrColor4f) const override {
+ return ConstantOutputForConstantInput(this->childProcessor(0), fColor);
+ }
+
GrColor4f fColor;
+
+ typedef GrFragmentProcessor INHERITED;
};
GrInvariantOutput childOut(0x0, kNone_GrColorComponentFlags);
@@ -288,7 +333,8 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProc
int cnt) {
class SeriesFragmentProcessor : public GrFragmentProcessor {
public:
- SeriesFragmentProcessor(sk_sp<GrFragmentProcessor>* children, int cnt){
+ SeriesFragmentProcessor(sk_sp<GrFragmentProcessor>* children, int cnt)
+ : INHERITED(OptFlags(children, cnt)) {
SkASSERT(cnt > 1);
this->initClassID<SeriesFragmentProcessor>();
for (int i = 0; i < cnt; ++i) {
@@ -317,8 +363,14 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProc
};
return new GLFP;
}
-
private:
+ static OptimizationFlags OptFlags(sk_sp<GrFragmentProcessor>* children, int cnt) {
+ OptimizationFlags flags = kAll_OptimizationFlags;
+ for (int i = 0; i < cnt && flags != kNone_OptimizationFlags; ++i) {
+ flags &= children[i]->optimizationFlags();
+ }
+ return flags;
+ }
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
@@ -328,6 +380,15 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProc
this->childProcessor(i).computeInvariantOutput(inout);
}
}
+ GrColor4f constantOutputForConstantInput(GrColor4f color) const override {
+ int childCnt = this->numChildProcessors();
+ for (int i = 0; i < childCnt; ++i) {
+ color = ConstantOutputForConstantInput(this->childProcessor(i), color);
+ }
+ return color;
+ }
+
+ typedef GrFragmentProcessor INHERITED;
};
if (!cnt) {
diff --git a/src/gpu/SkGrPriv.h b/src/gpu/SkGrPriv.h
index a4e3976126..9e2aad0ccd 100644
--- a/src/gpu/SkGrPriv.h
+++ b/src/gpu/SkGrPriv.h
@@ -8,10 +8,11 @@
#ifndef SkGrPriv_DEFINED
#define SkGrPriv_DEFINED
-#include "GrTypes.h"
#include "GrBlend.h"
+#include "GrTypes.h"
#include "SkImageInfo.h"
#include "SkMatrix.h"
+#include "SkPM4f.h"
#include "SkXfermodePriv.h"
class GrCaps;
@@ -102,6 +103,21 @@ bool SkPaintToGrPaintWithTexture(GrContext* context,
//////////////////////////////////////////////////////////////////////////////
+static inline SkPM4f GrColor4fToSkPM4f(const GrColor4f& c) {
+ SkPM4f pm4f;
+ pm4f.fVec[SkPM4f::R] = c.fRGBA[0];
+ pm4f.fVec[SkPM4f::G] = c.fRGBA[1];
+ pm4f.fVec[SkPM4f::B] = c.fRGBA[2];
+ pm4f.fVec[SkPM4f::A] = c.fRGBA[3];
+ return pm4f;
+}
+
+static inline GrColor4f SkPM4fToGrColor4f(const SkPM4f& c) {
+ return GrColor4f{c.r(), c.g(), c.b(), c.a()};
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo&, const GrCaps&);
bool GrPixelConfigToColorType(GrPixelConfig, SkColorType*);
diff --git a/src/gpu/effects/Gr1DKernelEffect.h b/src/gpu/effects/Gr1DKernelEffect.h
index 29e0e5dec2..67cc771c61 100644
--- a/src/gpu/effects/Gr1DKernelEffect.h
+++ b/src/gpu/effects/Gr1DKernelEffect.h
@@ -28,12 +28,11 @@ public:
kY_Direction,
};
- Gr1DKernelEffect(GrTexture* texture,
- Direction direction,
- int radius)
- : INHERITED(texture, nullptr, SkMatrix::I())
- , fDirection(direction)
- , fRadius(radius) {}
+ Gr1DKernelEffect(GrTexture* texture, Direction direction, int radius,
+ OptimizationFlags optFlags)
+ : INHERITED(texture, nullptr, SkMatrix::I(), optFlags)
+ , fDirection(direction)
+ , fRadius(radius) {}
virtual ~Gr1DKernelEffect() {}
@@ -51,7 +50,6 @@ public:
}
private:
-
Direction fDirection;
int fRadius;
diff --git a/src/gpu/effects/GrBicubicEffect.cpp b/src/gpu/effects/GrBicubicEffect.cpp
index 07d1c53011..cf3d2b5e79 100644
--- a/src/gpu/effects/GrBicubicEffect.cpp
+++ b/src/gpu/effects/GrBicubicEffect.cpp
@@ -132,21 +132,23 @@ void GrGLBicubicEffect::onSetData(const GrGLSLProgramDataManager& pdman,
GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkMatrix &matrix,
+ const SkMatrix& matrix,
const SkShader::TileMode tileModes[2])
- : INHERITED(texture, std::move(colorSpaceXform), matrix,
- GrSamplerParams(tileModes, GrSamplerParams::kNone_FilterMode))
- , fDomain(GrTextureDomain::IgnoredDomain()) {
+ : INHERITED(texture, std::move(colorSpaceXform), matrix,
+ GrSamplerParams(tileModes, GrSamplerParams::kNone_FilterMode),
+ ModulationFlags(texture->config()))
+ , fDomain(GrTextureDomain::IgnoredDomain()) {
this->initClassID<GrBicubicEffect>();
}
GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkMatrix &matrix,
+ const SkMatrix& matrix,
const SkRect& domain)
- : INHERITED(texture, std::move(colorSpaceXform), matrix,
- GrSamplerParams(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode))
- , fDomain(texture, domain, GrTextureDomain::kClamp_Mode) {
+ : INHERITED(texture, std::move(colorSpaceXform), matrix,
+ GrSamplerParams(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode),
+ ModulationFlags(texture->config()))
+ , fDomain(texture, domain, GrTextureDomain::kClamp_Mode) {
this->initClassID<GrBicubicEffect>();
}
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index 2380ad3435..74cf2ca44f 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -98,9 +98,9 @@ GrConfigConversionEffect::GrConfigConversionEffect(GrTexture* texture,
const GrSwizzle& swizzle,
PMConversion pmConversion,
const SkMatrix& matrix)
- : INHERITED(texture, nullptr, matrix)
- , fSwizzle(swizzle)
- , fPMConversion(pmConversion) {
+ : INHERITED(texture, nullptr, matrix, ModulationFlags(texture->config()))
+ , fSwizzle(swizzle)
+ , fPMConversion(pmConversion) {
this->initClassID<GrConfigConversionEffect>();
// We expect to get here with non-BGRA/RGBA only if we're doing not doing a premul/unpremul
// conversion.
@@ -116,7 +116,7 @@ GrConfigConversionEffect::GrConfigConversionEffect(GrContext* context,
const GrSwizzle& swizzle,
PMConversion pmConversion,
const SkMatrix& matrix)
- : INHERITED(context, proxy, nullptr, matrix)
+ : INHERITED(context, ModulationFlags(proxy->config()), proxy, nullptr, matrix)
, fSwizzle(swizzle)
, fPMConversion(pmConversion) {
this->initClassID<GrConfigConversionEffect>();
diff --git a/src/gpu/effects/GrConfigConversionEffect.h b/src/gpu/effects/GrConfigConversionEffect.h
index 46180bb2f2..151365b9b0 100644
--- a/src/gpu/effects/GrConfigConversionEffect.h
+++ b/src/gpu/effects/GrConfigConversionEffect.h
@@ -52,7 +52,6 @@ public:
static void TestForPreservingPMConversions(GrContext* context,
PMConversion* PMToUPMRule,
PMConversion* UPMToPMRule);
-
private:
GrConfigConversionEffect(GrTexture*, const GrSwizzle&, PMConversion, const SkMatrix& matrix);
diff --git a/src/gpu/effects/GrConstColorProcessor.cpp b/src/gpu/effects/GrConstColorProcessor.cpp
index e6568793df..3875ffcaa0 100644
--- a/src/gpu/effects/GrConstColorProcessor.cpp
+++ b/src/gpu/effects/GrConstColorProcessor.cpp
@@ -85,6 +85,19 @@ void GrConstColorProcessor::onComputeInvariantOutput(GrInvariantOutput* inout) c
}
}
+GrColor4f GrConstColorProcessor::constantOutputForConstantInput(GrColor4f input) const {
+ switch (fMode) {
+ case kIgnore_InputMode:
+ return fColor;
+ case kModulateA_InputMode:
+ return fColor.mulByScalar(input.fRGBA[3]);
+ case kModulateRGBA_InputMode:
+ return fColor.modulate(input);
+ }
+ SkFAIL("Unexpected mode");
+ return GrColor4f::TransparentBlack();
+}
+
void GrConstColorProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
GrProcessorKeyBuilder* b) const {
b->add32(fMode);
diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp
index 65ed87b687..4100a0fce2 100644
--- a/src/gpu/effects/GrConvexPolyEffect.cpp
+++ b/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -32,7 +32,7 @@ public:
private:
AARectEffect(GrPrimitiveEdgeType edgeType, const SkRect& rect)
- : fRect(rect), fEdgeType(edgeType) {
+ : INHERITED(kModulatesInput_OptimizationFlag), fRect(rect), fEdgeType(edgeType) {
this->initClassID<AARectEffect>();
}
@@ -339,8 +339,7 @@ GrGLSLFragmentProcessor* GrConvexPolyEffect::onCreateGLSLInstance() const {
}
GrConvexPolyEffect::GrConvexPolyEffect(GrPrimitiveEdgeType edgeType, int n, const SkScalar edges[])
- : fEdgeType(edgeType)
- , fEdgeCount(n) {
+ : INHERITED(kModulatesInput_OptimizationFlag), fEdgeType(edgeType), fEdgeCount(n) {
this->initClassID<GrConvexPolyEffect>();
// Factory function should have already ensured this.
SkASSERT(n <= kMaxEdges);
diff --git a/src/gpu/effects/GrDitherEffect.cpp b/src/gpu/effects/GrDitherEffect.cpp
index 2ba47d2e09..24e3ba6d50 100644
--- a/src/gpu/effects/GrDitherEffect.cpp
+++ b/src/gpu/effects/GrDitherEffect.cpp
@@ -26,9 +26,7 @@ public:
const char* name() const override { return "Dither"; }
private:
- DitherEffect() {
- this->initClassID<DitherEffect>();
- }
+ DitherEffect() : INHERITED(kNone_OptimizationFlags) { this->initClassID<DitherEffect>(); }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
diff --git a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
index 91301ff9ac..be6d4d8302 100644
--- a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
+++ b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
@@ -150,7 +150,8 @@ GrGaussianConvolutionFragmentProcessor::GrGaussianConvolutionFragmentProcessor(G
float gaussianSigma,
bool useBounds,
float bounds[2])
- : INHERITED(texture, direction, radius), fUseBounds(useBounds) {
+ : INHERITED(texture, direction, radius, ModulationFlags(texture->config()))
+ , fUseBounds(useBounds) {
this->initClassID<GrGaussianConvolutionFragmentProcessor>();
SkASSERT(radius <= kMaxKernelRadius);
int width = this->width();
diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
index 01fc6cec9c..9b670e120f 100644
--- a/src/gpu/effects/GrMatrixConvolutionEffect.cpp
+++ b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
@@ -156,12 +156,14 @@ GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(GrTexture* texture,
const SkIPoint& kernelOffset,
GrTextureDomain::Mode tileMode,
bool convolveAlpha)
- : INHERITED(texture, nullptr, SkMatrix::I()),
- fKernelSize(kernelSize),
- fGain(SkScalarToFloat(gain)),
- fBias(SkScalarToFloat(bias) / 255.0f),
- fConvolveAlpha(convolveAlpha),
- fDomain(texture, GrTextureDomain::MakeTexelDomainForMode(bounds, tileMode), tileMode) {
+ // To advertise either the modulation or opaqueness optimizations we'd have to examine the
+ // parameters.
+ : INHERITED(texture, nullptr, SkMatrix::I(), kNone_OptimizationFlags)
+ , fKernelSize(kernelSize)
+ , fGain(SkScalarToFloat(gain))
+ , fBias(SkScalarToFloat(bias) / 255.0f)
+ , fConvolveAlpha(convolveAlpha)
+ , fDomain(texture, GrTextureDomain::MakeTexelDomainForMode(bounds, tileMode), tileMode) {
this->initClassID<GrMatrixConvolutionEffect>();
for (int i = 0; i < kernelSize.width() * kernelSize.height(); i++) {
fKernel[i] = SkScalarToFloat(kernel[i]);
diff --git a/src/gpu/effects/GrOvalEffect.cpp b/src/gpu/effects/GrOvalEffect.cpp
index 21a4ba00e5..3b0a8871c4 100644
--- a/src/gpu/effects/GrOvalEffect.cpp
+++ b/src/gpu/effects/GrOvalEffect.cpp
@@ -64,9 +64,7 @@ void CircleEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
}
CircleEffect::CircleEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar r)
- : fCenter(c)
- , fRadius(r)
- , fEdgeType(edgeType) {
+ : INHERITED(kModulatesInput_OptimizationFlag), fCenter(c), fRadius(r), fEdgeType(edgeType) {
this->initClassID<CircleEffect>();
}
@@ -230,10 +228,12 @@ void EllipseEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
inout->mulByUnknownSingleComponent();
}
-EllipseEffect::EllipseEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar rx, SkScalar ry)
- : fCenter(c)
- , fRadii(SkVector::Make(rx, ry))
- , fEdgeType(edgeType) {
+EllipseEffect::EllipseEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar rx,
+ SkScalar ry)
+ : INHERITED(kModulatesInput_OptimizationFlag)
+ , fCenter(c)
+ , fRadii(SkVector::Make(rx, ry))
+ , fEdgeType(edgeType) {
this->initClassID<EllipseEffect>();
}
diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp
index adebc245a6..4397fcf930 100644
--- a/src/gpu/effects/GrRRectEffect.cpp
+++ b/src/gpu/effects/GrRRectEffect.cpp
@@ -95,9 +95,10 @@ void CircularRRectEffect::onComputeInvariantOutput(GrInvariantOutput* inout) con
CircularRRectEffect::CircularRRectEffect(GrPrimitiveEdgeType edgeType, uint32_t circularCornerFlags,
const SkRRect& rrect)
- : fRRect(rrect)
- , fEdgeType(edgeType)
- , fCircularCornerFlags(circularCornerFlags) {
+ : INHERITED(kModulatesInput_OptimizationFlag)
+ , fRRect(rrect)
+ , fEdgeType(edgeType)
+ , fCircularCornerFlags(circularCornerFlags) {
this->initClassID<CircularRRectEffect>();
}
@@ -410,8 +411,8 @@ private:
void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
- SkRRect fRRect;
- GrPrimitiveEdgeType fEdgeType;
+ SkRRect fRRect;
+ GrPrimitiveEdgeType fEdgeType;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
@@ -431,8 +432,7 @@ void EllipticalRRectEffect::onComputeInvariantOutput(GrInvariantOutput* inout) c
}
EllipticalRRectEffect::EllipticalRRectEffect(GrPrimitiveEdgeType edgeType, const SkRRect& rrect)
- : fRRect(rrect)
- , fEdgeType(edgeType) {
+ : INHERITED(kModulatesInput_OptimizationFlag), fRRect(rrect), fEdgeType(edgeType) {
this->initClassID<EllipticalRRectEffect>();
}
diff --git a/src/gpu/effects/GrSRGBEffect.cpp b/src/gpu/effects/GrSRGBEffect.cpp
index 67600ef320..9279586584 100644
--- a/src/gpu/effects/GrSRGBEffect.cpp
+++ b/src/gpu/effects/GrSRGBEffect.cpp
@@ -71,7 +71,9 @@ private:
///////////////////////////////////////////////////////////////////////////////
GrSRGBEffect::GrSRGBEffect(Mode mode)
- : fMode(mode) {
+ : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
+ kConstantOutputForConstantInput_OptimizationFlag)
+ , fMode(mode) {
this->initClassID<GrSRGBEffect>();
}
@@ -84,6 +86,26 @@ void GrSRGBEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
inout->setToUnknown();
}
+static inline float srgb_to_linear(float srgb) {
+ return (srgb <= 0.04045f) ? srgb / 12.92f : powf((srgb + 0.055f) / 1.055f, 2.4f);
+}
+static inline float linear_to_srgb(float linear) {
+ return (linear <= 0.0031308) ? linear * 12.92f : 1.055f * powf(linear, 1.f / 2.4f) - 0.055f;
+}
+
+GrColor4f GrSRGBEffect::constantOutputForConstantInput(GrColor4f input) const {
+ switch (fMode) {
+ case Mode::kLinearToSRGB:
+ return GrColor4f(linear_to_srgb(input.fRGBA[0]), linear_to_srgb(input.fRGBA[1]),
+ linear_to_srgb(input.fRGBA[2]), input.fRGBA[3]);
+ case Mode::kSRGBToLinear:
+ return GrColor4f(srgb_to_linear(input.fRGBA[0]), srgb_to_linear(input.fRGBA[1]),
+ srgb_to_linear(input.fRGBA[2]), input.fRGBA[3]);
+ }
+ SkFAIL("Unexpected mode");
+ return GrColor4f::TransparentBlack();
+}
+
///////////////////////////////////////////////////////////////////////////////
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSRGBEffect);
diff --git a/src/gpu/effects/GrSRGBEffect.h b/src/gpu/effects/GrSRGBEffect.h
index 2952689c4e..3d05dd646b 100644
--- a/src/gpu/effects/GrSRGBEffect.h
+++ b/src/gpu/effects/GrSRGBEffect.h
@@ -33,6 +33,7 @@ private:
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
+ GrColor4f constantOutputForConstantInput(GrColor4f input) const override;
Mode fMode;
diff --git a/src/gpu/effects/GrSimpleTextureEffect.h b/src/gpu/effects/GrSimpleTextureEffect.h
index bf013e9c83..c44ce44121 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.h
+++ b/src/gpu/effects/GrSimpleTextureEffect.h
@@ -13,6 +13,29 @@
class GrInvariantOutput;
+// In a few places below we rely on braced initialization order being defined by the C++ spec (left
+// to right). We use operator-> on a sk_sp and then in a later argument std::move() the sk_sp. GCC
+// 4.9.0 and earlier has a bug where the left to right order evaluation isn't implemented correctly.
+#if defined(__GNUC__) && !defined(__clang__)
+# define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+# if (GCC_VERSION > 40900)
+# define GCC_EVAL_ORDER_BUG 0
+# else
+# define GCC_EVAL_ORDER_BUG 1
+# endif
+# undef GCC_VERSION
+#else
+# define GCC_EVAL_ORDER_BUG 0
+#endif
+
+#if GCC_EVAL_ORDER_BUG
+# define PROXY_MOVE(X) (X)
+#else
+# define PROXY_MOVE(X) (std::move(X))
+#endif
+
+#undef GCC_EVAL_ORDER_BUG
+
/**
* The output color of this effect is a modulation of the input color and a sample from a texture.
* It allows explicit specification of the filtering and wrap modes (GrSamplerParams) and accepts
@@ -81,32 +104,41 @@ private:
sk_sp<GrColorSpaceXform> colorSpaceXform,
const SkMatrix& matrix,
GrSamplerParams::FilterMode filterMode)
- : GrSingleTextureEffect(texture, std::move(colorSpaceXform), matrix, filterMode) {
+ : INHERITED(texture, std::move(colorSpaceXform), matrix, filterMode,
+ ModulationFlags(texture->config())) {
this->initClassID<GrSimpleTextureEffect>();
}
GrSimpleTextureEffect(GrContext* ctx, sk_sp<GrTextureProxy> proxy,
- sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkMatrix& matrix,
+ sk_sp<GrColorSpaceXform> colorSpaceXform, const SkMatrix& matrix,
GrSamplerParams::FilterMode filterMode)
- : GrSingleTextureEffect(ctx, std::move(proxy), std::move(colorSpaceXform),
- matrix, filterMode) {
+ : INHERITED{ctx,
+ ModulationFlags(proxy->config()),
+ PROXY_MOVE(proxy),
+ std::move(colorSpaceXform),
+ matrix,
+ filterMode} {
this->initClassID<GrSimpleTextureEffect>();
}
GrSimpleTextureEffect(GrTexture* texture,
- sk_sp<GrColorSpaceXform> colorSpaceXform,
+ sk_sp<GrColorSpaceXform>colorSpaceXform,
const SkMatrix& matrix,
const GrSamplerParams& params)
- : GrSingleTextureEffect(texture, std::move(colorSpaceXform), matrix, params) {
+ : INHERITED(texture, std::move(colorSpaceXform), matrix, params,
+ ModulationFlags(texture->config())) {
this->initClassID<GrSimpleTextureEffect>();
}
GrSimpleTextureEffect(GrContext* ctx, sk_sp<GrTextureProxy> proxy,
- sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkMatrix& matrix,
+ sk_sp<GrColorSpaceXform> colorSpaceXform, const SkMatrix& matrix,
const GrSamplerParams& params)
- : GrSingleTextureEffect(ctx, std::move(proxy), std::move(colorSpaceXform), matrix, params) {
+ : INHERITED{ctx,
+ ModulationFlags(proxy->config()),
+ PROXY_MOVE(proxy),
+ std::move(colorSpaceXform),
+ matrix,
+ params} {
this->initClassID<GrSimpleTextureEffect>();
}
@@ -123,4 +155,6 @@ private:
typedef GrSingleTextureEffect INHERITED;
};
+#undef PROXY_MOVE
+
#endif
diff --git a/src/gpu/effects/GrSingleTextureEffect.cpp b/src/gpu/effects/GrSingleTextureEffect.cpp
index c493920d3d..acfc0d142d 100644
--- a/src/gpu/effects/GrSingleTextureEffect.cpp
+++ b/src/gpu/effects/GrSingleTextureEffect.cpp
@@ -12,10 +12,11 @@
GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture,
sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkMatrix& m)
- : fCoordTransform(m, texture, GrSamplerParams::kNone_FilterMode)
- , fTextureSampler(texture)
- , fColorSpaceXform(std::move(colorSpaceXform)) {
+ const SkMatrix& m, OptimizationFlags optFlags)
+ : INHERITED(optFlags)
+ , fCoordTransform(m, texture, GrSamplerParams::kNone_FilterMode)
+ , fTextureSampler(texture)
+ , fColorSpaceXform(std::move(colorSpaceXform)) {
this->addCoordTransform(&fCoordTransform);
this->addTextureSampler(&fTextureSampler);
}
@@ -23,56 +24,61 @@ GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture,
GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture,
sk_sp<GrColorSpaceXform> colorSpaceXform,
const SkMatrix& m,
- GrSamplerParams::FilterMode filterMode)
- : fCoordTransform(m, texture, filterMode)
- , fTextureSampler(texture, filterMode)
- , fColorSpaceXform(std::move(colorSpaceXform)) {
+ GrSamplerParams::FilterMode filterMode,
+ OptimizationFlags optFlags)
+ : INHERITED(optFlags)
+ , fCoordTransform(m, texture, filterMode)
+ , fTextureSampler(texture, filterMode)
+ , fColorSpaceXform(std::move(colorSpaceXform)) {
this->addCoordTransform(&fCoordTransform);
this->addTextureSampler(&fTextureSampler);
}
GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture,
sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkMatrix& m,
- const GrSamplerParams& params)
- : fCoordTransform(m, texture, params.filterMode())
- , fTextureSampler(texture, params)
- , fColorSpaceXform(std::move(colorSpaceXform)) {
+ const SkMatrix& m, const GrSamplerParams& params,
+ OptimizationFlags optFlags)
+ : INHERITED(optFlags)
+ , fCoordTransform(m, texture, params.filterMode())
+ , fTextureSampler(texture, params)
+ , fColorSpaceXform(std::move(colorSpaceXform)) {
this->addCoordTransform(&fCoordTransform);
this->addTextureSampler(&fTextureSampler);
}
-GrSingleTextureEffect::GrSingleTextureEffect(GrContext* ctx, sk_sp<GrTextureProxy> proxy,
+GrSingleTextureEffect::GrSingleTextureEffect(GrContext* ctx, OptimizationFlags optFlags,
+ sk_sp<GrTextureProxy> proxy,
sk_sp<GrColorSpaceXform> colorSpaceXform,
const SkMatrix& m)
- : fCoordTransform(ctx, m, proxy.get(), GrSamplerParams::kNone_FilterMode)
- , fTextureSampler(ctx->textureProvider(), std::move(proxy))
- , fColorSpaceXform(std::move(colorSpaceXform)) {
+ : INHERITED(optFlags)
+ , fCoordTransform(ctx, m, proxy.get(), GrSamplerParams::kNone_FilterMode)
+ , fTextureSampler(ctx->textureProvider(), std::move(proxy))
+ , fColorSpaceXform(std::move(colorSpaceXform)) {
this->addCoordTransform(&fCoordTransform);
this->addTextureSampler(&fTextureSampler);
}
-GrSingleTextureEffect::GrSingleTextureEffect(GrContext* ctx, sk_sp<GrTextureProxy> proxy,
+GrSingleTextureEffect::GrSingleTextureEffect(GrContext* ctx, OptimizationFlags optFlags,
+ sk_sp<GrTextureProxy> proxy,
sk_sp<GrColorSpaceXform> colorSpaceXform,
const SkMatrix& m,
GrSamplerParams::FilterMode filterMode)
- : fCoordTransform(ctx, m, proxy.get(), filterMode)
- , fTextureSampler(ctx->textureProvider(), std::move(proxy), filterMode)
- , fColorSpaceXform(std::move(colorSpaceXform)) {
+ : INHERITED(optFlags)
+ , fCoordTransform(ctx, m, proxy.get(), filterMode)
+ , fTextureSampler(ctx->textureProvider(), std::move(proxy), filterMode)
+ , fColorSpaceXform(std::move(colorSpaceXform)) {
this->addCoordTransform(&fCoordTransform);
this->addTextureSampler(&fTextureSampler);
}
-GrSingleTextureEffect::GrSingleTextureEffect(GrContext* ctx, sk_sp<GrTextureProxy> proxy,
+GrSingleTextureEffect::GrSingleTextureEffect(GrContext* ctx, OptimizationFlags optFlags,
+ sk_sp<GrTextureProxy> proxy,
sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkMatrix& m,
- const GrSamplerParams& params)
- : fCoordTransform(ctx, m, proxy.get(), params.filterMode())
- , fTextureSampler(ctx->textureProvider(), std::move(proxy), params)
- , fColorSpaceXform(std::move(colorSpaceXform)) {
+ const SkMatrix& m, const GrSamplerParams& params)
+ : INHERITED(optFlags)
+ , fCoordTransform(ctx, m, proxy.get(), params.filterMode())
+ , fTextureSampler(ctx->textureProvider(), std::move(proxy), params)
+ , fColorSpaceXform(std::move(colorSpaceXform)) {
this->addCoordTransform(&fCoordTransform);
this->addTextureSampler(&fTextureSampler);
}
-
-GrSingleTextureEffect::~GrSingleTextureEffect() {
-}
diff --git a/src/gpu/effects/GrSingleTextureEffect.h b/src/gpu/effects/GrSingleTextureEffect.h
index 1d0f27a4ff..29105b5cda 100644
--- a/src/gpu/effects/GrSingleTextureEffect.h
+++ b/src/gpu/effects/GrSingleTextureEffect.h
@@ -23,8 +23,6 @@ class GrTextureProxy;
*/
class GrSingleTextureEffect : public GrFragmentProcessor {
public:
- ~GrSingleTextureEffect() override;
-
SkString dumpInfo() const override {
SkString str;
str.appendf("Texture: %d", fTextureSampler.texture()->uniqueID().asUInt());
@@ -35,25 +33,26 @@ public:
protected:
/** unfiltered, clamp mode */
- GrSingleTextureEffect(GrTexture*, sk_sp<GrColorSpaceXform>, const SkMatrix&);
+ GrSingleTextureEffect(GrTexture*, sk_sp<GrColorSpaceXform>, const SkMatrix&,
+ OptimizationFlags optFlags);
/** clamp mode */
GrSingleTextureEffect(GrTexture*, sk_sp<GrColorSpaceXform>, const SkMatrix&,
- GrSamplerParams::FilterMode filterMode);
+ GrSamplerParams::FilterMode filterMode, OptimizationFlags optFlags);
GrSingleTextureEffect(GrTexture*,
sk_sp<GrColorSpaceXform>,
const SkMatrix&,
- const GrSamplerParams&);
+ const GrSamplerParams&,
+ OptimizationFlags optFlags);
/** unfiltered, clamp mode */
- GrSingleTextureEffect(GrContext*,
- sk_sp<GrTextureProxy>, sk_sp<GrColorSpaceXform>, const SkMatrix&);
+ GrSingleTextureEffect(GrContext*, OptimizationFlags, sk_sp<GrTextureProxy>,
+ sk_sp<GrColorSpaceXform>, const SkMatrix&);
/** clamp mode */
- GrSingleTextureEffect(GrContext*,
- sk_sp<GrTextureProxy>, sk_sp<GrColorSpaceXform>, const SkMatrix&,
+ GrSingleTextureEffect(GrContext*, OptimizationFlags, sk_sp<GrTextureProxy>,
+ sk_sp<GrColorSpaceXform>, const SkMatrix&,
GrSamplerParams::FilterMode filterMode);
- GrSingleTextureEffect(GrContext*,
- sk_sp<GrTextureProxy>, sk_sp<GrColorSpaceXform>, const SkMatrix&,
- const GrSamplerParams&);
+ GrSingleTextureEffect(GrContext*, OptimizationFlags, sk_sp<GrTextureProxy>,
+ sk_sp<GrColorSpaceXform>, const SkMatrix&, const GrSamplerParams&);
/**
* Can be used as a helper to implement subclass onComputeInvariantOutput(). It assumes that
@@ -71,6 +70,19 @@ protected:
}
}
+ /**
+ * Can be used as a helper to implement subclass onOptimizationFlags(). It assumes that
+ * the subclass output color will be a modulation of the input color with a value read from the
+ * texture.
+ */
+ static OptimizationFlags ModulationFlags(GrPixelConfig config) {
+ if (GrPixelConfigIsOpaque(config)) {
+ return kModulatesInput_OptimizationFlag | kPreservesOpaqueInput_OptimizationFlag;
+ } else {
+ return kModulatesInput_OptimizationFlag;
+ }
+ }
+
private:
GrCoordTransform fCoordTransform;
TextureSampler fTextureSampler;
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index 095f100593..7ab598fd1f 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -208,14 +208,25 @@ sk_sp<GrFragmentProcessor> GrTextureDomainEffect::Make(GrTexture* texture,
}
}
+inline GrFragmentProcessor::OptimizationFlags GrTextureDomainEffect::OptFlags(
+ GrTexture* texture, GrTextureDomain::Mode mode) {
+ if (mode == GrTextureDomain::kDecal_Mode || !GrPixelConfigIsOpaque(texture->config())) {
+ return GrFragmentProcessor::kModulatesInput_OptimizationFlag;
+ } else {
+ return GrFragmentProcessor::kModulatesInput_OptimizationFlag |
+ GrFragmentProcessor::kPreservesOpaqueInput_OptimizationFlag;
+ }
+}
+
GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture,
sk_sp<GrColorSpaceXform> colorSpaceXform,
const SkMatrix& matrix,
const SkRect& domain,
GrTextureDomain::Mode mode,
GrSamplerParams::FilterMode filterMode)
- : GrSingleTextureEffect(texture, std::move(colorSpaceXform), matrix, filterMode)
- , fTextureDomain(texture, domain, mode) {
+ : GrSingleTextureEffect(texture, std::move(colorSpaceXform), matrix, filterMode,
+ OptFlags(texture, mode))
+ , fTextureDomain(texture, domain, mode) {
SkASSERT(mode != GrTextureDomain::kRepeat_Mode ||
filterMode == GrSamplerParams::kNone_FilterMode);
this->initClassID<GrTextureDomainEffect>();
@@ -323,7 +334,8 @@ sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(GrTe
GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
GrTexture* texture, const SkIRect& subset, const SkIPoint& deviceSpaceOffset)
- : fTextureSampler(texture, GrSamplerParams::ClampNoFilter())
+ : INHERITED(kModulatesInput_OptimizationFlag)
+ , fTextureSampler(texture, GrSamplerParams::ClampNoFilter())
, fTextureDomain(texture, GrTextureDomain::MakeTexelDomain(subset),
GrTextureDomain::kDecal_Mode) {
this->addTextureSampler(&fTextureSampler);
diff --git a/src/gpu/effects/GrTextureDomain.h b/src/gpu/effects/GrTextureDomain.h
index 66bd2201e3..6758d9045e 100644
--- a/src/gpu/effects/GrTextureDomain.h
+++ b/src/gpu/effects/GrTextureDomain.h
@@ -178,6 +178,8 @@ private:
GrTextureDomain::Mode,
GrSamplerParams::FilterMode);
+ static OptimizationFlags OptFlags(GrTexture* texture, GrTextureDomain::Mode mode);
+
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index d98478747a..af32adec8b 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -19,7 +19,7 @@ class ComposeTwoFragmentProcessor : public GrFragmentProcessor {
public:
ComposeTwoFragmentProcessor(sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst,
SkBlendMode mode)
- : fMode(mode) {
+ : INHERITED(OptFlags(src.get(), dst.get(), mode)), fMode(mode) {
this->initClassID<ComposeTwoFragmentProcessor>();
SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst));
@@ -35,7 +35,18 @@ public:
SkBlendMode getMode() const { return fMode; }
-protected:
+private:
+ static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
+ const GrFragmentProcessor* dst, SkBlendMode mode) {
+ // We only attempt the constant output optimization.
+ // The CPU and GPU implementations differ significantly for the advanced modes.
+ if (mode <= SkBlendMode::kLastSeparableMode && src->hasConstantOutputForConstantInput() &&
+ dst->hasConstantOutputForConstantInput()) {
+ return kConstantOutputForConstantInput_OptimizationFlag;
+ }
+ return kNone_OptimizationFlags;
+ }
+
bool onIsEqual(const GrFragmentProcessor& other) const override {
const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
return fMode == cs.fMode;
@@ -45,7 +56,17 @@ protected:
inout->setToUnknown();
}
-private:
+ GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
+ float alpha = input.fRGBA[3];
+ input = input.opaque();
+ GrColor4f srcColor = ConstantOutputForConstantInput(this->childProcessor(0), input);
+ GrColor4f dstColor = ConstantOutputForConstantInput(this->childProcessor(1), input);
+ SkPM4f src = GrColor4fToSkPM4f(srcColor);
+ SkPM4f dst = GrColor4fToSkPM4f(dstColor);
+ auto proc = SkXfermode::GetProc4f(fMode);
+ return SkPM4fToGrColor4f(proc(src, dst)).mulByScalar(alpha);
+ }
+
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
SkBlendMode fMode;
@@ -145,8 +166,7 @@ public:
};
ComposeOneFragmentProcessor(sk_sp<GrFragmentProcessor> dst, SkBlendMode mode, Child child)
- : fMode(mode)
- , fChild(child) {
+ : INHERITED(OptFlags(dst.get(), mode)), fMode(mode), fChild(child) {
this->initClassID<ComposeOneFragmentProcessor>();
SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(std::move(dst));
SkASSERT(0 == dstIndex);
@@ -172,7 +192,16 @@ public:
Child child() const { return fChild; }
-protected:
+private:
+ OptimizationFlags OptFlags(const GrFragmentProcessor* child, SkBlendMode mode) {
+ // We only attempt the constant output optimization.
+ // The CPU and GPU implementations differ significantly for the advanced modes.
+ if (mode <= SkBlendMode::kLastSeparableMode && child->hasConstantOutputForConstantInput()) {
+ return kConstantOutputForConstantInput_OptimizationFlag;
+ }
+ return kNone_OptimizationFlags;
+ }
+
bool onIsEqual(const GrFragmentProcessor& that) const override {
return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
}
@@ -203,6 +232,21 @@ protected:
}
}
+ GrColor4f constantOutputForConstantInput(GrColor4f inputColor) const override {
+ GrColor4f childColor =
+ ConstantOutputForConstantInput(this->childProcessor(0), GrColor4f::OpaqueWhite());
+ SkPM4f src, dst;
+ if (kSrc_Child == fChild) {
+ src = GrColor4fToSkPM4f(childColor);
+ dst = GrColor4fToSkPM4f(inputColor);
+ } else {
+ src = GrColor4fToSkPM4f(inputColor);
+ dst = GrColor4fToSkPM4f(childColor);
+ }
+ auto proc = SkXfermode::GetProc4f(fMode);
+ return SkPM4fToGrColor4f(proc(src, dst));
+ }
+
private:
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
diff --git a/src/gpu/effects/GrYUVEffect.cpp b/src/gpu/effects/GrYUVEffect.cpp
index 254cdffd2b..6d917f36d5 100644
--- a/src/gpu/effects/GrYUVEffect.cpp
+++ b/src/gpu/effects/GrYUVEffect.cpp
@@ -155,19 +155,17 @@ public:
};
private:
- YUVtoRGBEffect(GrContext* ctx,
- sk_sp<GrTextureProxy> yProxy,
- sk_sp<GrTextureProxy> uProxy,
- sk_sp<GrTextureProxy> vProxy,
- const SkMatrix yuvMatrix[3], GrSamplerParams::FilterMode uvFilterMode,
- SkYUVColorSpace colorSpace, bool nv12)
- : fYTransform(ctx, yuvMatrix[0], yProxy.get(), GrSamplerParams::kNone_FilterMode)
- , fYSampler(ctx->textureProvider(), std::move(yProxy))
- , fUTransform(ctx, yuvMatrix[1], uProxy.get(), uvFilterMode)
- , fUSampler(ctx->textureProvider(), std::move(uProxy), uvFilterMode)
- , fVSampler(ctx->textureProvider(), vProxy, uvFilterMode)
- , fColorSpace(colorSpace)
- , fNV12(nv12) {
+ YUVtoRGBEffect(GrContext* ctx, sk_sp<GrTextureProxy> yProxy, sk_sp<GrTextureProxy> uProxy,
+ sk_sp<GrTextureProxy> vProxy, const SkMatrix yuvMatrix[3],
+ GrSamplerParams::FilterMode uvFilterMode, SkYUVColorSpace colorSpace, bool nv12)
+ : INHERITED(kPreservesOpaqueInput_OptimizationFlag)
+ , fYTransform(ctx, yuvMatrix[0], yProxy.get(), GrSamplerParams::kNone_FilterMode)
+ , fYSampler(ctx->textureProvider(), std::move(yProxy))
+ , fUTransform(ctx, yuvMatrix[1], uProxy.get(), uvFilterMode)
+ , fUSampler(ctx->textureProvider(), std::move(uProxy), uvFilterMode)
+ , fVSampler(ctx->textureProvider(), vProxy, uvFilterMode)
+ , fColorSpace(colorSpace)
+ , fNV12(nv12) {
this->initClassID<YUVtoRGBEffect>();
this->addCoordTransform(&fYTransform);
this->addTextureSampler(&fYSampler);
@@ -228,8 +226,10 @@ public:
RGBToYUVEffect(sk_sp<GrFragmentProcessor> rgbFP, SkYUVColorSpace colorSpace,
OutputChannels output)
- : fColorSpace(colorSpace)
- , fOutputChannels(output) {
+ // This could advertise kConstantOutputForConstantInput, but doesn't seem useful.
+ : INHERITED(kPreservesOpaqueInput_OptimizationFlag)
+ , fColorSpace(colorSpace)
+ , fOutputChannels(output) {
this->initClassID<RGBToYUVEffect>();
this->registerChildProcessor(std::move(rgbFP));
}