aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar egdaniel <egdaniel@google.com>2015-11-23 13:20:41 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-11-23 13:20:42 -0800
commitc4b72720e75313079212e69e46a5ef7c474b2305 (patch)
treeb0bf74db86503bd22684bb3107613db4e6625244
parent60ce86d4718dab83f33488ec41710ad6763fc7f8 (diff)
Don't create a GXPFactory when blend is SrcOver
-rw-r--r--gm/beziereffects.cpp6
-rw-r--r--gm/bigrrectaaeffect.cpp2
-rw-r--r--gm/convexpolyeffect.cpp4
-rw-r--r--gm/rrects.cpp2
-rw-r--r--gm/texturedomaineffect.cpp2
-rw-r--r--gm/yuvtorgbeffect.cpp2
-rw-r--r--include/core/SkXfermode.h26
-rw-r--r--include/gpu/GrPaint.h9
-rw-r--r--include/gpu/GrXferProcessor.h8
-rw-r--r--include/gpu/effects/GrCoverageSetOpXP.h5
-rw-r--r--include/gpu/effects/GrPorterDuffXferProcessor.h31
-rw-r--r--src/core/SkImageFilter.cpp1
-rw-r--r--src/core/SkXfermode.cpp21
-rw-r--r--src/effects/SkArithmeticMode_gpu.h4
-rw-r--r--src/effects/SkBlurMaskFilter.cpp2
-rw-r--r--src/effects/SkDisplacementMapEffect.cpp1
-rw-r--r--src/effects/SkGpuBlurUtils.cpp4
-rw-r--r--src/effects/SkLightingImageFilter.cpp1
-rw-r--r--src/effects/SkMorphologyImageFilter.cpp2
-rw-r--r--src/effects/SkPerlinNoiseShader.cpp1
-rw-r--r--src/effects/SkXfermodeImageFilter.cpp1
-rw-r--r--src/gpu/GrContext.cpp6
-rw-r--r--src/gpu/GrDrawTarget.cpp2
-rw-r--r--src/gpu/GrPaint.cpp9
-rw-r--r--src/gpu/GrPipeline.cpp32
-rw-r--r--src/gpu/GrPipelineBuilder.cpp10
-rw-r--r--src/gpu/GrPipelineBuilder.h7
-rw-r--r--src/gpu/GrYUVProvider.cpp1
-rw-r--r--src/gpu/SkGr.cpp9
-rw-r--r--src/gpu/batches/GrDefaultPathRenderer.cpp3
-rw-r--r--src/gpu/effects/GrConfigConversionEffect.cpp3
-rw-r--r--src/gpu/effects/GrCustomXfermode.cpp4
-rw-r--r--src/gpu/effects/GrDisableColorXP.h4
-rw-r--r--src/gpu/effects/GrPorterDuffXferProcessor.cpp62
-rw-r--r--tests/TessellatingPathRendererTests.cpp2
35 files changed, 199 insertions, 90 deletions
diff --git a/gm/beziereffects.cpp b/gm/beziereffects.cpp
index 58d7fef3d3..ba163a3840 100644
--- a/gm/beziereffects.cpp
+++ b/gm/beziereffects.cpp
@@ -221,6 +221,8 @@ protected:
SkASSERT(tt.target());
GrPipelineBuilder pipelineBuilder;
+ pipelineBuilder.setXPFactory(
+ GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
pipelineBuilder.setRenderTarget(rt);
BezierCubicOrConicTestBatch::Geometry geometry;
@@ -366,6 +368,8 @@ protected:
SkASSERT(tt.target());
GrPipelineBuilder pipelineBuilder;
+ pipelineBuilder.setXPFactory(
+ GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
pipelineBuilder.setRenderTarget(rt);
BezierCubicOrConicTestBatch::Geometry geometry;
@@ -604,6 +608,8 @@ protected:
SkASSERT(tt.target());
GrPipelineBuilder pipelineBuilder;
+ pipelineBuilder.setXPFactory(
+ GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
pipelineBuilder.setRenderTarget(rt);
GrPathUtils::QuadUVMatrix DevToUV(pts);
diff --git a/gm/bigrrectaaeffect.cpp b/gm/bigrrectaaeffect.cpp
index 472910b5df..18a0c6ef7d 100644
--- a/gm/bigrrectaaeffect.cpp
+++ b/gm/bigrrectaaeffect.cpp
@@ -71,6 +71,8 @@ protected:
return;
}
GrPipelineBuilder pipelineBuilder;
+ pipelineBuilder.setXPFactory(
+ GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
SkRRect rrect = fRRects[curRRect];
rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
diff --git a/gm/convexpolyeffect.cpp b/gm/convexpolyeffect.cpp
index 4f38436726..f040b90ed2 100644
--- a/gm/convexpolyeffect.cpp
+++ b/gm/convexpolyeffect.cpp
@@ -190,6 +190,8 @@ protected:
}
GrPipelineBuilder pipelineBuilder;
+ pipelineBuilder.setXPFactory(
+ GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
pipelineBuilder.addCoverageFragmentProcessor(fp);
pipelineBuilder.setRenderTarget(rt);
@@ -239,6 +241,8 @@ protected:
}
GrPipelineBuilder pipelineBuilder;
+ pipelineBuilder.setXPFactory(
+ GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
pipelineBuilder.addCoverageFragmentProcessor(fp);
pipelineBuilder.setRenderTarget(rt);
diff --git a/gm/rrects.cpp b/gm/rrects.cpp
index e48b8c8c8d..fbe7ad1836 100644
--- a/gm/rrects.cpp
+++ b/gm/rrects.cpp
@@ -107,6 +107,8 @@ protected:
return;
}
GrPipelineBuilder pipelineBuilder;
+ pipelineBuilder.setXPFactory(
+ GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
SkRRect rrect = fRRects[curRRect];
rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
diff --git a/gm/texturedomaineffect.cpp b/gm/texturedomaineffect.cpp
index a2dc4b01b8..3eaba90806 100644
--- a/gm/texturedomaineffect.cpp
+++ b/gm/texturedomaineffect.cpp
@@ -117,6 +117,8 @@ protected:
for (int m = 0; m < GrTextureDomain::kModeCount; ++m) {
GrTextureDomain::Mode mode = (GrTextureDomain::Mode) m;
GrPipelineBuilder pipelineBuilder;
+ pipelineBuilder.setXPFactory(
+ GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
SkAutoTUnref<const GrFragmentProcessor> fp(
GrTextureDomainEffect::Create(texture, textureMatrices[tm],
GrTextureDomain::MakeTexelDomain(texture,
diff --git a/gm/yuvtorgbeffect.cpp b/gm/yuvtorgbeffect.cpp
index 5f7cc1314d..66ade25184 100644
--- a/gm/yuvtorgbeffect.cpp
+++ b/gm/yuvtorgbeffect.cpp
@@ -115,6 +115,8 @@ protected:
for (int i = 0; i < 6; ++i) {
GrPipelineBuilder pipelineBuilder;
+ pipelineBuilder.setXPFactory(
+ GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
SkAutoTUnref<GrFragmentProcessor> fp(
GrYUVtoRGBEffect::Create(texture[indices[i][0]],
texture[indices[i][1]],
diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h
index cb9557f92c..91268ab5f1 100644
--- a/include/core/SkXfermode.h
+++ b/include/core/SkXfermode.h
@@ -204,18 +204,26 @@ public:
const GrFragmentProcessor* dst) const;
/** A subclass may implement this factory function to work with the GPU backend. It is legal
- to call this with xpf NULL to simply test the return value. If xpf is non-NULL then the
- xfermode may optionally allocate a factory to return to the caller as *xpf. The caller
- will install it and own a ref to it. Since the xfermode may or may not assign *xpf, the
- caller should set *xpf to NULL beforehand. XferProcessors cannot use a background texture.
- */
+ to call this with xpf NULL to simply test the return value. If xpf is non-NULL then the
+ xfermode may optionally allocate a factory to return to the caller as *xpf. The caller
+ will install it and own a ref to it. Since the xfermode may or may not assign *xpf, the
+ caller should set *xpf to NULL beforehand. XferProcessors cannot use a background texture.
+ */
virtual bool asXPFactory(GrXPFactory** xpf) const;
/** Returns true if the xfermode can be expressed as an xfer processor factory (xpFactory).
- This helper calls the asXPFactory() virtual. If the xfermode is NULL, it is treated as
- kSrcOver_Mode. It is legal to call this with xpf param NULL to simply test the return value.
- */
- static bool AsXPFactory(SkXfermode*, GrXPFactory**);
+ This helper calls the asXPFactory() virtual. If the xfermode is NULL, it is treated as
+ kSrcOver_Mode. It is legal to call this with xpf param NULL to simply test the return value.
+ */
+ static inline bool AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
+ if (nullptr == xfermode) {
+ if (xpf) {
+ *xpf = nullptr;
+ }
+ return true;
+ }
+ return xfermode->asXPFactory(xpf);
+ }
SK_TO_STRING_PUREVIRT()
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h
index 9d0fe5575e..152cb51d7e 100644
--- a/include/gpu/GrPaint.h
+++ b/include/gpu/GrPaint.h
@@ -57,7 +57,7 @@ public:
bool isAntiAlias() const { return fAntiAlias; }
const GrXPFactory* setXPFactory(const GrXPFactory* xpFactory) {
- fXPFactory.reset(SkRef(xpFactory));
+ fXPFactory.reset(SkSafeRef(xpFactory));
return xpFactory;
}
@@ -100,10 +100,7 @@ public:
this->numCoverageFragmentProcessors(); }
const GrXPFactory* getXPFactory() const {
- if (!fXPFactory) {
- fXPFactory.reset(GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode));
- }
- return fXPFactory.get();
+ return fXPFactory;
}
const GrFragmentProcessor* getColorFragmentProcessor(int i) const {
@@ -127,7 +124,7 @@ public:
fCoverageFragmentProcessors[i]->ref();
}
- fXPFactory.reset(SkRef(paint.getXPFactory()));
+ fXPFactory.reset(SkSafeRef(paint.getXPFactory()));
return *this;
}
diff --git a/include/gpu/GrXferProcessor.h b/include/gpu/GrXferProcessor.h
index 4accbc84fa..64a0e1ab55 100644
--- a/include/gpu/GrXferProcessor.h
+++ b/include/gpu/GrXferProcessor.h
@@ -316,14 +316,6 @@ public:
bool hasMixedSamples,
const DstTexture*,
const GrCaps& caps) const;
-
- /**
- * This function returns true if the GrXferProcessor generated from this factory will be able to
- * correctly blend when using RGB coverage. The knownColor and knownColorFlags represent the
- * final computed color from the color stages.
- */
- virtual bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const = 0;
-
/**
* Known color information after blending, but before accounting for any coverage.
*/
diff --git a/include/gpu/effects/GrCoverageSetOpXP.h b/include/gpu/effects/GrCoverageSetOpXP.h
index 8511074cbd..a17cf81232 100644
--- a/include/gpu/effects/GrCoverageSetOpXP.h
+++ b/include/gpu/effects/GrCoverageSetOpXP.h
@@ -23,11 +23,6 @@ class GrCoverageSetOpXPFactory : public GrXPFactory {
public:
static GrXPFactory* Create(SkRegion::Op regionOp, bool invertCoverage = false);
- bool supportsRGBCoverage(GrColor /*knownColor*/,
- uint32_t /*knownColorFlags*/) const override {
- return true;
- }
-
void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
GrXPFactory::InvariantBlendedColor*) const override;
diff --git a/include/gpu/effects/GrPorterDuffXferProcessor.h b/include/gpu/effects/GrPorterDuffXferProcessor.h
index d297e32908..3dc503305f 100644
--- a/include/gpu/effects/GrPorterDuffXferProcessor.h
+++ b/include/gpu/effects/GrPorterDuffXferProcessor.h
@@ -18,13 +18,36 @@ class GrPorterDuffXPFactory : public GrXPFactory {
public:
static GrXPFactory* Create(SkXfermode::Mode mode);
- bool supportsRGBCoverage(GrColor /*knownColor*/, uint32_t /*knownColorFlags*/) const override {
- return true;
- }
-
void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
GrXPFactory::InvariantBlendedColor*) const override;
+ static GrXferProcessor* CreateSrcOverXferProcessor(const GrCaps& caps,
+ const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& coveragePOI,
+ bool hasMixedSamples,
+ const GrXferProcessor::DstTexture*);
+
+ static inline void SrcOverInvariantBlendedColor(
+ GrColor inputColor,
+ GrColorComponentFlags validColorFlags,
+ bool isOpaque,
+ GrXPFactory::InvariantBlendedColor* blendedColor) {
+ if (!isOpaque) {
+ blendedColor->fWillBlendWithDst = true;
+ blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
+ return;
+ }
+ blendedColor->fWillBlendWithDst = false;
+
+ blendedColor->fKnownColor = inputColor;
+ blendedColor->fKnownColorFlags = validColorFlags;
+ }
+
+ static bool SrcOverWillNeedDstTexture(const GrCaps& caps,
+ const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& coveragePOI,
+ bool hasMixedSamples);
+
private:
GrPorterDuffXPFactory(SkXfermode::Mode);
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp
index abac24cf3f..6a3286ed67 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -377,6 +377,7 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Cont
if (this->asFragmentProcessor(&fp, srcTexture, matrix, bounds)) {
SkASSERT(fp);
paint.addColorFragmentProcessor(fp)->unref();
+ paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
if (drawContext) {
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 9083814d1a..79de322c2d 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -660,26 +660,6 @@ bool SkXfermode::asXPFactory(GrXPFactory**) const {
return false;
}
-
-#if SK_SUPPORT_GPU
-#include "effects/GrPorterDuffXferProcessor.h"
-
-bool SkXfermode::AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
- if (nullptr == xfermode) {
- if (xpf) {
- *xpf = GrPorterDuffXPFactory::Create(kSrcOver_Mode);
- }
- return true;
- } else {
- return xfermode->asXPFactory(xpf);
- }
-}
-#else
-bool SkXfermode::AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
- return false;
-}
-#endif
-
SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
// no-op. subclasses should override this
return dst;
@@ -920,6 +900,7 @@ void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
#if SK_SUPPORT_GPU
#include "effects/GrCustomXfermode.h"
+#include "effects/GrPorterDuffXferProcessor.h"
#include "effects/GrXfermodeFragmentProcessor.h"
bool SkProcCoeffXfermode::asFragmentProcessor(const GrFragmentProcessor** fp,
diff --git a/src/effects/SkArithmeticMode_gpu.h b/src/effects/SkArithmeticMode_gpu.h
index ee3e73abb0..b24d23a6e6 100644
--- a/src/effects/SkArithmeticMode_gpu.h
+++ b/src/effects/SkArithmeticMode_gpu.h
@@ -81,10 +81,6 @@ public:
return new GrArithmeticXPFactory(k1, k2, k3, k4, enforcePMColor);
}
- bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const override {
- return true;
- }
-
void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
GrXPFactory::InvariantBlendedColor*) const override;
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index 0dedf0208c..8dd82c5ac3 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -1262,6 +1262,8 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src,
// outer: dst = dst * (1 - src)
// = 0 * src + (1 - src) * dst
paint.setCoverageSetOpXPFactory(SkRegion::kDifference_Op);
+ } else {
+ paint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);
}
SkAutoTUnref<GrDrawContext> drawContext(context->drawContext((*result)->asRenderTarget()));
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 77d6cb84aa..fe918581c4 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -445,6 +445,7 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src,
offsetMatrix,
color,
colorBM.dimensions()))->unref();
+ paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
SkIRect colorBounds = bounds;
colorBounds.offset(-colorOffset);
SkMatrix matrix;
diff --git a/src/effects/SkGpuBlurUtils.cpp b/src/effects/SkGpuBlurUtils.cpp
index 2e6a7d6bde..8ab05dd862 100644
--- a/src/effects/SkGpuBlurUtils.cpp
+++ b/src/effects/SkGpuBlurUtils.cpp
@@ -59,6 +59,7 @@ static void convolve_gaussian_1d(GrDrawContext* drawContext,
SkAutoTUnref<GrFragmentProcessor> conv(GrConvolutionEffect::CreateGaussian(
texture, direction, radius, sigma, useBounds, bounds));
paint.addColorFragmentProcessor(conv);
+ paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
SkMatrix localMatrix = SkMatrix::MakeTrans(srcOffset.x(), srcOffset.y());
drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), dstRect, localMatrix);
}
@@ -89,6 +90,7 @@ static void convolve_gaussian_2d(GrDrawContext* drawContext,
srcBounds ? GrTextureDomain::kDecal_Mode : GrTextureDomain::kIgnore_Mode,
true, sigmaX, sigmaY));
paint.addColorFragmentProcessor(conv);
+ paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), dstRect, localMatrix);
}
@@ -247,6 +249,7 @@ GrTexture* GaussianBlur(GrContext* context,
GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
paint.addColorTextureProcessor(srcTexture, matrix, params);
}
+ paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
i < scaleFactorY ? 0.5f : 1.0f);
@@ -374,6 +377,7 @@ GrTexture* GaussianBlur(GrContext* context,
// FIXME: this should be mitchell, not bilinear.
GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
paint.addColorTextureProcessor(srcTexture, matrix, params);
+ paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
SkRect dstRect(srcRect);
scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index 4bb755e3ed..9b6a20f0ef 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -354,6 +354,7 @@ void SkLightingImageFilterInternal::drawRect(GrDrawContext* drawContext,
GrPaint paint;
GrFragmentProcessor* fp = this->getFragmentProcessor(src, matrix, bounds, boundaryMode);
paint.addColorFragmentProcessor(fp)->unref();
+ paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);
}
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index fbc071fe58..484ed57f37 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -479,6 +479,7 @@ void apply_morphology_rect(GrDrawContext* drawContext,
radius,
morphType,
bounds))->unref();
+ paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect),
SkRect::Make(srcRect));
}
@@ -496,6 +497,7 @@ void apply_morphology_rect_no_bounds(GrDrawContext* drawContext,
direction,
radius,
morphType))->unref();
+ paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect),
SkRect::Make(srcRect));
}
diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp
index c1a6f701d7..916cf78f0d 100644
--- a/src/effects/SkPerlinNoiseShader.cpp
+++ b/src/effects/SkPerlinNoiseShader.cpp
@@ -608,7 +608,6 @@ const GrFragmentProcessor* GrPerlinNoiseEffect::TestCreate(GrProcessorTestData*
SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
stitchTiles ? &tileSize : nullptr));
- GrPaint grPaint;
return shader->asFragmentProcessor(d->fContext,
GrTest::TestMatrix(d->fRandom), nullptr,
kNone_SkFilterQuality);
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
index 28d9a00c84..38d1e5e6b4 100644
--- a/src/effects/SkXfermodeImageFilter.cpp
+++ b/src/effects/SkXfermodeImageFilter.cpp
@@ -191,6 +191,7 @@ bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
if (xferFP) {
paint.addColorFragmentProcessor(xferFP)->unref();
}
+ paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
if (!drawContext) {
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 348cdbaaca..920e3c4bbd 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -276,7 +276,6 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
SkAutoTUnref<const GrFragmentProcessor> fp;
SkMatrix textureMatrix;
textureMatrix.setIDiv(tempTexture->width(), tempTexture->height());
- GrPaint paint;
if (applyPremulToSrc) {
fp.reset(this->createUPMToPMEffect(tempTexture, tempDrawInfo.fSwapRAndB,
textureMatrix));
@@ -324,7 +323,9 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
if (!drawContext) {
return false;
}
+ GrPaint paint;
paint.addColorFragmentProcessor(fp);
+ paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
drawContext->drawRect(GrClip::WideOpen(), paint, matrix, rect, nullptr);
@@ -412,7 +413,6 @@ bool GrContext::readSurfacePixels(GrSurface* src,
SkMatrix textureMatrix;
textureMatrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
textureMatrix.postIDiv(src->width(), src->height());
- GrPaint paint;
SkAutoTUnref<const GrFragmentProcessor> fp;
if (unpremul) {
fp.reset(this->createPMToUPMEffect(src->asTexture(), tempDrawInfo.fSwapRAndB,
@@ -430,7 +430,9 @@ bool GrContext::readSurfacePixels(GrSurface* src,
GrConfigConversionEffect::kNone_PMConversion, textureMatrix));
}
if (fp) {
+ GrPaint paint;
paint.addColorFragmentProcessor(fp);
+ paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
SkAutoTUnref<GrDrawContext> drawContext(this->drawContext(temp->asRenderTarget()));
drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), rect, nullptr);
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 062a42fc5b..01d4f63bc5 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -431,6 +431,8 @@ void GrDrawTarget::clear(const SkIRect* rect,
}
GrPipelineBuilder pipelineBuilder;
+ pipelineBuilder.setXPFactory(
+ GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
pipelineBuilder.setRenderTarget(renderTarget);
this->drawNonAARect(pipelineBuilder, color, SkMatrix::I(), *rect);
diff --git a/src/gpu/GrPaint.cpp b/src/gpu/GrPaint.cpp
index 6f218a4b0b..1ec8e502be 100644
--- a/src/gpu/GrPaint.cpp
+++ b/src/gpu/GrPaint.cpp
@@ -50,7 +50,14 @@ bool GrPaint::isConstantBlendedColor(GrColor* color) const {
kRGBA_GrColorComponentFlags, false);
GrXPFactory::InvariantBlendedColor blendedColor;
- fXPFactory->getInvariantBlendedColor(colorProcInfo, &blendedColor);
+ if (fXPFactory) {
+ fXPFactory->getInvariantBlendedColor(colorProcInfo, &blendedColor);
+ } else {
+ GrPorterDuffXPFactory::SrcOverInvariantBlendedColor(colorProcInfo.color(),
+ colorProcInfo.validFlags(),
+ colorProcInfo.isOpaque(),
+ &blendedColor);
+ }
if (kRGBA_GrColorComponentFlags == blendedColor.fKnownColorFlags) {
*color = blendedColor.fKnownColor;
diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp
index 073349be1e..73b20a9042 100644
--- a/src/gpu/GrPipeline.cpp
+++ b/src/gpu/GrPipeline.cpp
@@ -21,10 +21,23 @@ GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args,
const GrPipelineBuilder& builder = *args.fPipelineBuilder;
// Create XferProcessor from DS's XPFactory
- SkAutoTUnref<GrXferProcessor> xferProcessor(
- builder.getXPFactory()->createXferProcessor(args.fColorPOI, args.fCoveragePOI,
- builder.hasMixedSamples(), &args.fDstTexture,
- *args.fCaps));
+ const GrXPFactory* xpFactory = builder.getXPFactory();
+ SkAutoTUnref<GrXferProcessor> xferProcessor;
+ if (xpFactory) {
+ xferProcessor.reset(xpFactory->createXferProcessor(args.fColorPOI,
+ args.fCoveragePOI,
+ builder.hasMixedSamples(),
+ &args.fDstTexture,
+ *args.fCaps));
+ } else {
+ xferProcessor.reset(GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
+ *args.fCaps,
+ args.fColorPOI,
+ args.fCoveragePOI,
+ builder.hasMixedSamples(),
+ &args.fDstTexture));
+ }
+
if (!xferProcessor) {
return nullptr;
}
@@ -55,7 +68,7 @@ GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args,
}
GrPipeline* pipeline = new (memory) GrPipeline;
- pipeline->fXferProcessor.reset(xferProcessor.get());
+ pipeline->fXferProcessor.reset(xferProcessor);
pipeline->fRenderTarget.reset(builder.fRenderTarget.get());
SkASSERT(pipeline->fRenderTarget);
@@ -123,7 +136,14 @@ GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args,
}
GrXPFactory::InvariantBlendedColor blendedColor;
- builder.fXPFactory->getInvariantBlendedColor(args.fColorPOI, &blendedColor);
+ if (xpFactory) {
+ xpFactory->getInvariantBlendedColor(args.fColorPOI, &blendedColor);
+ } else {
+ GrPorterDuffXPFactory::SrcOverInvariantBlendedColor(args.fColorPOI.color(),
+ args.fColorPOI.validFlags(),
+ args.fColorPOI.isOpaque(),
+ &blendedColor);
+ }
if (blendedColor.fWillBlendWithDst) {
opts->fFlags |= GrPipelineOptimizations::kWillColorBlendWithDst_Flag;
}
diff --git a/src/gpu/GrPipelineBuilder.cpp b/src/gpu/GrPipelineBuilder.cpp
index ab185505d6..ce465c1c71 100644
--- a/src/gpu/GrPipelineBuilder.cpp
+++ b/src/gpu/GrPipelineBuilder.cpp
@@ -31,7 +31,7 @@ GrPipelineBuilder::GrPipelineBuilder(const GrPaint& paint, GrRenderTarget* rt, c
fCoverageFragmentProcessors.push_back(SkRef(paint.getCoverageFragmentProcessor(i)));
}
- fXPFactory.reset(SkRef(paint.getXPFactory()));
+ fXPFactory.reset(SkSafeRef(paint.getXPFactory()));
this->setRenderTarget(rt);
@@ -51,8 +51,12 @@ GrPipelineBuilder::GrPipelineBuilder(const GrPaint& paint, GrRenderTarget* rt, c
bool GrPipelineBuilder::willXPNeedDstTexture(const GrCaps& caps,
const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const {
- return this->getXPFactory()->willNeedDstTexture(caps, colorPOI, coveragePOI,
- this->hasMixedSamples());
+ if (this->getXPFactory()) {
+ return this->getXPFactory()->willNeedDstTexture(caps, colorPOI, coveragePOI,
+ this->hasMixedSamples());
+ }
+ return GrPorterDuffXPFactory::SrcOverWillNeedDstTexture(caps, colorPOI, coveragePOI,
+ this->hasMixedSamples());
}
void GrPipelineBuilder::AutoRestoreFragmentProcessorState::set(
diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h
index 010685b3e2..bf0bed56c9 100644
--- a/src/gpu/GrPipelineBuilder.h
+++ b/src/gpu/GrPipelineBuilder.h
@@ -150,7 +150,7 @@ public:
* and the dst color are blended.
*/
const GrXPFactory* setXPFactory(const GrXPFactory* xpFactory) {
- fXPFactory.reset(SkRef(xpFactory));
+ fXPFactory.reset(SkSafeRef(xpFactory));
return xpFactory;
}
@@ -171,10 +171,7 @@ public:
}
const GrXPFactory* getXPFactory() const {
- if (!fXPFactory) {
- fXPFactory.reset(GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode));
- }
- return fXPFactory.get();
+ return fXPFactory;
}
/**
diff --git a/src/gpu/GrYUVProvider.cpp b/src/gpu/GrYUVProvider.cpp
index 93859483ad..014c30574a 100644
--- a/src/gpu/GrYUVProvider.cpp
+++ b/src/gpu/GrYUVProvider.cpp
@@ -128,6 +128,7 @@ GrTexture* GrYUVProvider::refAsTexture(GrContext* ctx, const GrSurfaceDesc& desc
yuvInfo.fSize,
yuvInfo.fColorSpace));
paint.addColorFragmentProcessor(yuvToRgbProcessor);
+ paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
const SkRect r = SkRect::MakeIWH(yuvInfo.fSize[0].fWidth, yuvInfo.fSize[0].fHeight);
SkAutoTUnref<GrDrawContext> drawContext(ctx->drawContext(renderTarget));
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 411b5b2b60..954bb80852 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -489,13 +489,8 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context,
SkXfermode* mode = skPaint.getXfermode();
GrXPFactory* xpFactory = nullptr;
- if (!SkXfermode::AsXPFactory(mode, &xpFactory)) {
- // Fall back to src-over
- // return false here?
- xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrcOver_Mode);
- }
- SkASSERT(xpFactory);
- grPaint->setXPFactory(xpFactory)->unref();
+ SkXfermode::AsXPFactory(mode, &xpFactory);
+ SkSafeUnref(grPaint->setXPFactory(xpFactory));
#ifndef SK_IGNORE_GPU_DITHER
if (skPaint.isDither() && grPaint->numColorFragmentProcessors() > 0) {
diff --git a/src/gpu/batches/GrDefaultPathRenderer.cpp b/src/gpu/batches/GrDefaultPathRenderer.cpp
index d0777e253f..fa2ffe0b4d 100644
--- a/src/gpu/batches/GrDefaultPathRenderer.cpp
+++ b/src/gpu/batches/GrDefaultPathRenderer.cpp
@@ -564,7 +564,8 @@ bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target,
const bool isHairline = stroke->isHairlineStyle();
// Save the current xp on the draw state so we can reset it if needed
- SkAutoTUnref<const GrXPFactory> backupXPFactory(SkRef(pipelineBuilder->getXPFactory()));
+ const GrXPFactory* xpFactory = pipelineBuilder->getXPFactory();
+ SkAutoTUnref<const GrXPFactory> backupXPFactory(SkSafeRef(xpFactory));
// face culling doesn't make sense here
SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace());
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index 2510b5c9d7..4df894b40a 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -223,6 +223,7 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
tempTex, false, *pmToUPMRule, SkMatrix::I()));
paint1.addColorFragmentProcessor(pmToUPM1);
+ paint1.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
SkAutoTUnref<GrDrawContext> readDrawContext(
@@ -241,6 +242,7 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
readTex->readPixels(0, 0, 256, 256, kRGBA_8888_GrPixelConfig, firstRead);
paint2.addColorFragmentProcessor(upmToPM);
+ paint2.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
SkAutoTUnref<GrDrawContext> tempDrawContext(
context->drawContext(tempTex->asRenderTarget()));
@@ -255,6 +257,7 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
kSrcRect);
paint3.addColorFragmentProcessor(pmToUPM2);
+ paint3.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
readDrawContext.reset(context->drawContext(readTex->asRenderTarget()));
if (!readDrawContext) {
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index 6b3a20ec2d..90ab030d24 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -321,10 +321,6 @@ class CustomXPFactory : public GrXPFactory {
public:
CustomXPFactory(SkXfermode::Mode mode);
- bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const override {
- return true;
- }
-
void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
GrXPFactory::InvariantBlendedColor*) const override;
diff --git a/src/gpu/effects/GrDisableColorXP.h b/src/gpu/effects/GrDisableColorXP.h
index caa0eecec8..a79dd9b971 100644
--- a/src/gpu/effects/GrDisableColorXP.h
+++ b/src/gpu/effects/GrDisableColorXP.h
@@ -17,10 +17,6 @@ class GrDisableColorXPFactory : public GrXPFactory {
public:
static GrXPFactory* Create() { return new GrDisableColorXPFactory; }
- bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const override {
- return true;
- }
-
void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
GrXPFactory::InvariantBlendedColor* blendedColor) const override {
blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index 4245caafed..2323c67040 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -830,3 +830,65 @@ void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp,
*outPrimary = blendFormula.fPrimaryOutputType;
*outSecondary = blendFormula.fSecondaryOutputType;
}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+// SrcOver Global functions
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
+ const GrCaps& caps,
+ const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& covPOI,
+ bool hasMixedSamples,
+ const GrXferProcessor::DstTexture* dstTexture) {
+ BlendFormula blendFormula;
+ if (covPOI.isFourChannelOutput()) {
+ if (kRGBA_GrColorComponentFlags == colorPOI.validFlags() &&
+ !caps.shaderCaps()->dualSourceBlendingSupport() &&
+ !caps.shaderCaps()->dstReadInShaderSupport()) {
+ // If we don't have dual source blending or in shader dst reads, we fall
+ // back to this trick for rendering SrcOver LCD text instead of doing a
+ // dst copy.
+ SkASSERT(!dstTexture || !dstTexture->texture());
+ return PDLCDXferProcessor::Create(SkXfermode::kSrcOver_Mode, colorPOI);
+ }
+ blendFormula = get_lcd_blend_formula(covPOI, SkXfermode::kSrcOver_Mode);
+ } else {
+ blendFormula = get_blend_formula(colorPOI, covPOI, hasMixedSamples,
+ SkXfermode::kSrcOver_Mode);
+ }
+
+ if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
+ return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkXfermode::kSrcOver_Mode);
+ }
+
+ SkASSERT(!dstTexture || !dstTexture->texture());
+ return new PorterDuffXferProcessor(blendFormula);
+}
+
+bool GrPorterDuffXPFactory::SrcOverWillNeedDstTexture(const GrCaps& caps,
+ const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& covPOI,
+ bool hasMixedSamples) {
+ if (caps.shaderCaps()->dstReadInShaderSupport() ||
+ caps.shaderCaps()->dualSourceBlendingSupport()) {
+ return false;
+ }
+
+ // When we have four channel coverage we always need to read the dst in order to correctly
+ // blend. The one exception is when we are using srcover mode and we know the input color
+ // into the XP.
+ if (covPOI.isFourChannelOutput()) {
+ if (kRGBA_GrColorComponentFlags == colorPOI.validFlags() &&
+ !caps.shaderCaps()->dstReadInShaderSupport()) {
+ return false;
+ }
+ return get_lcd_blend_formula(covPOI, SkXfermode::kSrcOver_Mode).hasSecondaryOutput();
+ }
+ // We fallback on the shader XP when the blend formula would use dual source blending but we
+ // don't have support for it.
+ return get_blend_formula(colorPOI, covPOI,
+ hasMixedSamples, SkXfermode::kSrcOver_Mode).hasSecondaryOutput();
+}
+
diff --git a/tests/TessellatingPathRendererTests.cpp b/tests/TessellatingPathRendererTests.cpp
index 219397bc11..a6eabfdaaf 100644
--- a/tests/TessellatingPathRendererTests.cpp
+++ b/tests/TessellatingPathRendererTests.cpp
@@ -236,6 +236,8 @@ static void test_path(GrDrawTarget* dt, GrRenderTarget* rt, GrResourceProvider*
const SkPath& path) {
GrTessellatingPathRenderer tess;
GrPipelineBuilder pipelineBuilder;
+ pipelineBuilder.setXPFactory(
+ GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
pipelineBuilder.setRenderTarget(rt);
GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
GrPathRenderer::DrawPathArgs args;