Clarify when tweak alpha for coverage optimizaton can occur.
Also refer to it directly rather than using the term "modulate"
Change-Id: Ifa44a4d46e1be11b567943f58ead24e38f10d03b
Reviewed-on: https://skia-review.googlesource.com/8488
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/include/gpu/GrFragmentProcessor.h b/include/gpu/GrFragmentProcessor.h
index 96ca1c8..55dc08f 100644
--- a/include/gpu/GrFragmentProcessor.h
+++ b/include/gpu/GrFragmentProcessor.h
@@ -99,11 +99,20 @@
}
/**
- * True if the processor's output is a modulation of its input color or alpha with a computed
- * premultiplied color or alpha in the 0..1 range. If true and the blend mode allows it we may
- * fold coverage into the first color fragment processor's input.
+ * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
+ * output under the following scenario:
+ * * all the color fragment processors report true to this query,
+ * * all the coverage fragment processors report true to this query,
+ * * the blend mode arithmetic allows for it it.
+ * To be compatible a fragment processor's output must be a modulation of its input color or
+ * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
+ * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
+ * value cannot depend on the input's color channels unless it unpremultiplies the input color
+ * channels by the input alpha.
*/
- bool modulatesInput() const { return SkToBool(fFlags & kModulatesInput_OptimizationFlag); }
+ bool compatibleWithCoverageAsAlpha() const {
+ return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
+ }
/**
* If this is true then all opaque input colors to the processor produce opaque output colors.
@@ -207,10 +216,10 @@
protected:
enum OptimizationFlags : uint32_t {
kNone_OptimizationFlags,
- kModulatesInput_OptimizationFlag = 0x1,
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
kPreservesOpaqueInput_OptimizationFlag = 0x2,
kConstantOutputForConstantInput_OptimizationFlag = 0x4,
- kAll_OptimizationFlags = kModulatesInput_OptimizationFlag |
+ kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
kPreservesOpaqueInput_OptimizationFlag |
kConstantOutputForConstantInput_OptimizationFlag
};
diff --git a/include/gpu/effects/GrConstColorProcessor.h b/include/gpu/effects/GrConstColorProcessor.h
index 44e8cb1..b543aa5 100644
--- a/include/gpu/effects/GrConstColorProcessor.h
+++ b/include/gpu/effects/GrConstColorProcessor.h
@@ -46,7 +46,7 @@
static OptimizationFlags OptFlags(GrColor4f color, InputMode mode) {
OptimizationFlags flags = kConstantOutputForConstantInput_OptimizationFlag;
if (mode != kIgnore_InputMode) {
- flags |= kModulatesInput_OptimizationFlag;
+ flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag;
}
if (color.isOpaque()) {
flags |= kPreservesOpaqueInput_OptimizationFlag;
diff --git a/src/effects/GrAlphaThresholdFragmentProcessor.cpp b/src/effects/GrAlphaThresholdFragmentProcessor.cpp
index f0338a6..3d0defb 100644
--- a/src/effects/GrAlphaThresholdFragmentProcessor.cpp
+++ b/src/effects/GrAlphaThresholdFragmentProcessor.cpp
@@ -32,9 +32,10 @@
inline GrFragmentProcessor::OptimizationFlags GrAlphaThresholdFragmentProcessor::OptFlags(float outerThreshold) {
if (outerThreshold >= 1.f) {
- return kPreservesOpaqueInput_OptimizationFlag | kModulatesInput_OptimizationFlag;
+ return kPreservesOpaqueInput_OptimizationFlag |
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag;
} else {
- return kModulatesInput_OptimizationFlag;
+ return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
}
}
diff --git a/src/effects/GrCircleBlurFragmentProcessor.cpp b/src/effects/GrCircleBlurFragmentProcessor.cpp
index 70c4247..c95b41e 100644
--- a/src/effects/GrCircleBlurFragmentProcessor.cpp
+++ b/src/effects/GrCircleBlurFragmentProcessor.cpp
@@ -86,7 +86,7 @@
float textureRadius,
float solidRadius,
GrTexture* blurProfile)
- : INHERITED(kModulatesInput_OptimizationFlag)
+ : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fCircle(circle)
, fSolidRadius(solidRadius)
, fTextureRadius(textureRadius)
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index c070ccf..5249696 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -973,7 +973,7 @@
GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture* blurProfile,
GrSLPrecision precision)
- : INHERITED(kModulatesInput_OptimizationFlag)
+ : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fRect(rect)
, fSigma(sigma)
, fBlurProfileSampler(blurProfile)
@@ -1197,7 +1197,7 @@
}
GrRRectBlurEffect::GrRRectBlurEffect(float sigma, const SkRRect& rrect, GrTexture* ninePatchTexture)
- : INHERITED(kModulatesInput_OptimizationFlag)
+ : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fRRect(rrect)
, fSigma(sigma)
, fNinePatchSampler(ninePatchTexture) {
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index a3efbcf..e3f0f3a 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -1691,7 +1691,7 @@
const SkMatrix& matrix,
BoundaryMode boundaryMode,
const SkIRect* srcBounds)
- // Perhaps this could advertise the opaque or modulating optimizations?
+ // Perhaps this could advertise the opaque or coverage-as-alpha optimizations?
: INHERITED(texture, nullptr, SkMatrix::I(), kNone_OptimizationFlags)
, fLight(light)
, fSurfaceScale(surfaceScale)
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index 03f0cbc..23efdd3 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -1584,8 +1584,10 @@
/////////////////////////////////////////////////////////////////////
inline GrFragmentProcessor::OptimizationFlags GrGradientEffect::OptFlags(bool isOpaque) {
- return isOpaque ? kPreservesOpaqueInput_OptimizationFlag | kModulatesInput_OptimizationFlag
- : kModulatesInput_OptimizationFlag;
+ return isOpaque
+ ? kPreservesOpaqueInput_OptimizationFlag |
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag
+ : kCompatibleWithCoverageAsAlpha_OptimizationFlag;
}
GrGradientEffect::GrGradientEffect(const CreateArgs& args, bool isOpaque)
diff --git a/src/gpu/GrProcOptInfo.cpp b/src/gpu/GrProcOptInfo.cpp
index 92e6838..9eda9bb 100644
--- a/src/gpu/GrProcOptInfo.cpp
+++ b/src/gpu/GrProcOptInfo.cpp
@@ -12,7 +12,7 @@
void GrProcOptInfo::analyzeProcessors(const GrFragmentProcessor* const* processors, int cnt) {
for (int i = 0; i < cnt; ++i) {
bool knowCurrentOutput = fProcessorsVisitedWithKnownOutput == fTotalProcessorsVisited;
- if (!knowCurrentOutput && !fAllProcessorsModulatePremul && !fIsOpaque) {
+ if (!knowCurrentOutput && !fAllProcessorsCompatibleWithCoverageAsAlpha && !fIsOpaque) {
fTotalProcessorsVisited += cnt - i;
return;
}
@@ -24,8 +24,8 @@
} else if (fIsOpaque && !fp->preservesOpaqueInput()) {
fIsOpaque = false;
}
- if (fAllProcessorsModulatePremul && !fp->modulatesInput()) {
- fAllProcessorsModulatePremul = false;
+ if (fAllProcessorsCompatibleWithCoverageAsAlpha && !fp->compatibleWithCoverageAsAlpha()) {
+ fAllProcessorsCompatibleWithCoverageAsAlpha = false;
}
++fTotalProcessorsVisited;
}
diff --git a/src/gpu/GrProcOptInfo.h b/src/gpu/GrProcOptInfo.h
index 2c55233..1a85789 100644
--- a/src/gpu/GrProcOptInfo.h
+++ b/src/gpu/GrProcOptInfo.h
@@ -52,7 +52,9 @@
fLastKnownOutputColor == GrColor4f::OpaqueWhite();
}
bool isOpaque() const { return fIsOpaque; }
- bool allProcessorsModulateByPremul() const { return fAllProcessorsModulatePremul; }
+ bool allProcessorsCompatibleWithCoverageAsAlpha() const {
+ return fAllProcessorsCompatibleWithCoverageAsAlpha;
+ }
bool isLCDCoverage() const { return fIsLCDCoverage; }
/**
@@ -91,7 +93,7 @@
int fProcessorsVisitedWithKnownOutput = -1;
bool fIsLCDCoverage = false;
bool fIsOpaque = false;
- bool fAllProcessorsModulatePremul = true;
+ bool fAllProcessorsCompatibleWithCoverageAsAlpha = true;
GrColor4f fLastKnownOutputColor;
};
diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp
index 907a9e5..0248beb 100644
--- a/src/gpu/effects/GrConvexPolyEffect.cpp
+++ b/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -31,7 +31,9 @@
private:
AARectEffect(GrPrimitiveEdgeType edgeType, const SkRect& rect)
- : INHERITED(kModulatesInput_OptimizationFlag), fRect(rect), fEdgeType(edgeType) {
+ : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+ , fRect(rect)
+ , fEdgeType(edgeType) {
this->initClassID<AARectEffect>();
}
@@ -327,7 +329,9 @@
}
GrConvexPolyEffect::GrConvexPolyEffect(GrPrimitiveEdgeType edgeType, int n, const SkScalar edges[])
- : INHERITED(kModulatesInput_OptimizationFlag), fEdgeType(edgeType), fEdgeCount(n) {
+ : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+ , fEdgeType(edgeType)
+ , fEdgeCount(n) {
this->initClassID<GrConvexPolyEffect>();
// Factory function should have already ensured this.
SkASSERT(n <= kMaxEdges);
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index bc11d7e..d733069 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -300,7 +300,7 @@
*/
OptFlags flags = kNone_OptFlags;
- if (analysis.fColorPOI.allProcessorsModulateByPremul()) {
+ if (analysis.fColorPOI.allProcessorsCompatibleWithCoverageAsAlpha()) {
flags |= kCanTweakAlphaForCoverage_OptFlag;
}
return flags;
diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
index fc8add8..0cae0ba 100644
--- a/src/gpu/effects/GrMatrixConvolutionEffect.cpp
+++ b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
@@ -159,7 +159,8 @@
GrTextureDomain::Mode tileMode,
bool convolveAlpha)
// To advertise the preserves opaqueness optimization we'd have to examine the parameters.
- : INHERITED(texture, nullptr, SkMatrix::I(), kModulatesInput_OptimizationFlag)
+ : INHERITED(texture, nullptr, SkMatrix::I(),
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fKernelSize(kernelSize)
, fGain(SkScalarToFloat(gain))
, fBias(SkScalarToFloat(bias) / 255.0f)
diff --git a/src/gpu/effects/GrOvalEffect.cpp b/src/gpu/effects/GrOvalEffect.cpp
index 36db836..62b1c52 100644
--- a/src/gpu/effects/GrOvalEffect.cpp
+++ b/src/gpu/effects/GrOvalEffect.cpp
@@ -57,7 +57,10 @@
}
CircleEffect::CircleEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar r)
- : INHERITED(kModulatesInput_OptimizationFlag), fCenter(c), fRadius(r), fEdgeType(edgeType) {
+ : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+ , fCenter(c)
+ , fRadius(r)
+ , fEdgeType(edgeType) {
this->initClassID<CircleEffect>();
}
@@ -219,7 +222,7 @@
EllipseEffect::EllipseEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar rx,
SkScalar ry)
- : INHERITED(kModulatesInput_OptimizationFlag)
+ : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fCenter(c)
, fRadii(SkVector::Make(rx, ry))
, fEdgeType(edgeType) {
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index a04bb5b..ead4ed6 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -465,7 +465,7 @@
if (!fBlendFormula.usesInputColor()) {
optFlags |= GrXferProcessor::kIgnoreColor_OptFlag;
}
- if (analysis.fColorPOI.allProcessorsModulateByPremul() &&
+ if (analysis.fColorPOI.allProcessorsCompatibleWithCoverageAsAlpha() &&
fBlendFormula.canTweakAlphaForCoverage() && !analysis.fCoveragePOI.isLCDCoverage()) {
optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
}
diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp
index 29d3d3d..7253de8 100644
--- a/src/gpu/effects/GrRRectEffect.cpp
+++ b/src/gpu/effects/GrRRectEffect.cpp
@@ -88,7 +88,7 @@
CircularRRectEffect::CircularRRectEffect(GrPrimitiveEdgeType edgeType, uint32_t circularCornerFlags,
const SkRRect& rrect)
- : INHERITED(kModulatesInput_OptimizationFlag)
+ : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fRRect(rrect)
, fEdgeType(edgeType)
, fCircularCornerFlags(circularCornerFlags) {
@@ -421,7 +421,9 @@
}
EllipticalRRectEffect::EllipticalRRectEffect(GrPrimitiveEdgeType edgeType, const SkRRect& rrect)
- : INHERITED(kModulatesInput_OptimizationFlag), fRRect(rrect), fEdgeType(edgeType) {
+ : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+ , fRRect(rrect)
+ , fEdgeType(edgeType) {
this->initClassID<EllipticalRRectEffect>();
}
diff --git a/src/gpu/effects/GrSingleTextureEffect.h b/src/gpu/effects/GrSingleTextureEffect.h
index 894334b..74b25c7 100644
--- a/src/gpu/effects/GrSingleTextureEffect.h
+++ b/src/gpu/effects/GrSingleTextureEffect.h
@@ -54,15 +54,17 @@
sk_sp<GrColorSpaceXform>, const SkMatrix&, const GrSamplerParams&);
/**
- * 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.
+ * Can be used as a helper to decide which fragment processor OptimizationFlags should be set.
+ * This assumes that the subclass output color will be a modulation of the input color with a
+ * value read from the texture and that the texture contains premultiplied color or alpha values
+ * that are in range.
*/
static OptimizationFlags ModulationFlags(GrPixelConfig config) {
if (GrPixelConfigIsOpaque(config)) {
- return kModulatesInput_OptimizationFlag | kPreservesOpaqueInput_OptimizationFlag;
+ return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
+ kPreservesOpaqueInput_OptimizationFlag;
} else {
- return kModulatesInput_OptimizationFlag;
+ return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
}
}
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index 142cd1d..39bc3cc 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -251,9 +251,9 @@
inline GrFragmentProcessor::OptimizationFlags GrTextureDomainEffect::OptFlags(
GrPixelConfig config, GrTextureDomain::Mode mode) {
if (mode == GrTextureDomain::kDecal_Mode || !GrPixelConfigIsOpaque(config)) {
- return GrFragmentProcessor::kModulatesInput_OptimizationFlag;
+ return GrFragmentProcessor::kCompatibleWithCoverageAsAlpha_OptimizationFlag;
} else {
- return GrFragmentProcessor::kModulatesInput_OptimizationFlag |
+ return GrFragmentProcessor::kCompatibleWithCoverageAsAlpha_OptimizationFlag |
GrFragmentProcessor::kPreservesOpaqueInput_OptimizationFlag;
}
}
@@ -398,7 +398,7 @@
GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
GrTexture* texture, const SkIRect& subset, const SkIPoint& deviceSpaceOffset)
- : INHERITED(kModulatesInput_OptimizationFlag)
+ : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fTextureSampler(texture, GrSamplerParams::ClampNoFilter())
, fTextureDomain(texture, GrTextureDomain::MakeTexelDomain(subset),
GrTextureDomain::kDecal_Mode) {
@@ -422,7 +422,7 @@
sk_sp<GrTextureProxy> proxy,
const SkIRect& subset,
const SkIPoint& deviceSpaceOffset)
- : INHERITED(kModulatesInput_OptimizationFlag)
+ : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fTextureSampler(context->textureProvider(), proxy, GrSamplerParams::ClampNoFilter())
, fTextureDomain(proxy.get(), GrTextureDomain::MakeTexelDomain(subset),
GrTextureDomain::kDecal_Mode) {
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index 5433b67..8488fec 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -289,9 +289,12 @@
case SkBlendMode::kSrcIn:
case SkBlendMode::kDstIn:
case SkBlendMode::kModulate:
- flags = fp->preservesOpaqueInput()
- ? kPreservesOpaqueInput_OptimizationFlag | kModulatesInput_OptimizationFlag
- : kModulatesInput_OptimizationFlag;
+ if (fp->preservesOpaqueInput()) {
+ flags = kPreservesOpaqueInput_OptimizationFlag |
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag;
+ } else {
+ flags = kCompatibleWithCoverageAsAlpha_OptimizationFlag;
+ }
break;
// Produces zero when both are opaque, indeterminate if one is opaque.
diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp
index a69371d..8801a34 100644
--- a/tests/ProcessorTest.cpp
+++ b/tests/ProcessorTest.cpp
@@ -316,7 +316,7 @@
for (int j = 0; j < timesToInvokeFactory; ++j) {
fp = FPFactory::MakeIdx(i, &testData);
if (!fp->hasConstantOutputForConstantInput() && !fp->preservesOpaqueInput() &&
- !fp->modulatesInput()) {
+ !fp->compatibleWithCoverageAsAlpha()) {
continue;
}
test_draw_op(rtc.get(), fp, dataTexture.get());
@@ -340,7 +340,7 @@
for (int x = 0; x < 256 && passing; ++x) {
GrColor input = texel_color(x, y);
GrColor output = rgbaData.get()[y * 256 + x];
- if (fp->modulatesInput()) {
+ if (fp->compatibleWithCoverageAsAlpha()) {
// A modulating processor is allowed to modulate either the input color or
// just the input alpha.
bool legalColorModulation =