Revert "Remove GrPipeline from GrDrawOp."
authorBrian Salomon <bsalomon@google.com>
Thu, 16 Mar 2017 19:51:42 +0000 (19:51 +0000)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Thu, 16 Mar 2017 19:51:55 +0000 (19:51 +0000)
This reverts commit 2bf4b3a97b770811d9e0558dbbfbdb57cfafbdb7.

Reason for revert: nanobench assertion

Original change's description:
> Remove GrPipeline from GrDrawOp.
>
> GrDrawOp subclasses are now free to construct their pipelines at flush time and now in theory could use multiple GrPipelines for multipass rendering.
>
> GrProcessorSet may be used to retain the processors from a GrPaint with "pending execution" style refs.
>
> NVPR and Instanced rendering are updated to create their pipelines at flush time without a GrPipelineBuilder.
>
> The monolithic pipeline creation/management that was on GrDrawOp is moved to GrMeshDrawOp. However, this is temporary and will be removed in coming changes.
>
> Change-Id: I124282e3cea5d070970b5460c8a679fcaf7a8eff
> Reviewed-on: https://skia-review.googlesource.com/7279
> Commit-Queue: Brian Salomon <bsalomon@google.com>
> Reviewed-by: Robert Phillips <robertphillips@google.com>
>

TBR=bsalomon@google.com,robertphillips@google.com,csmartdalton@google.com,reviews@skia.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

Change-Id: I1bc64f6cbbd5f482417637a034342c2b5371dc5c
Reviewed-on: https://skia-review.googlesource.com/9817
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>

34 files changed:
include/gpu/GrProgramElement.h
src/gpu/GrAppliedClip.h
src/gpu/GrOpFlushState.cpp
src/gpu/GrOpFlushState.h
src/gpu/GrPipeline.cpp
src/gpu/GrPrimitiveProcessor.h
src/gpu/GrProcessorSet.cpp
src/gpu/GrProcessorSet.h
src/gpu/GrRenderTargetContext.cpp
src/gpu/GrRenderTargetContext.h
src/gpu/GrRenderTargetOpList.cpp
src/gpu/GrRenderTargetOpList.h
src/gpu/GrTextureOpList.cpp
src/gpu/GrXferProcessor.cpp
src/gpu/GrXferProcessor.h
src/gpu/effects/GrCoverageSetOpXP.h
src/gpu/effects/GrCustomXfermode.cpp
src/gpu/effects/GrDisableColorXP.h
src/gpu/effects/GrPorterDuffXferProcessor.cpp
src/gpu/effects/GrPorterDuffXferProcessor.h
src/gpu/instanced/GLInstancedRendering.cpp
src/gpu/instanced/GLInstancedRendering.h
src/gpu/instanced/InstancedRendering.cpp
src/gpu/instanced/InstancedRendering.h
src/gpu/ops/GrDrawOp.h
src/gpu/ops/GrDrawPathOp.cpp
src/gpu/ops/GrDrawPathOp.h
src/gpu/ops/GrMeshDrawOp.cpp
src/gpu/ops/GrMeshDrawOp.h
src/gpu/ops/GrOp.h
src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
src/gpu/text/GrStencilAndCoverTextContext.cpp
tests/GpuSampleLocationsTest.cpp
tests/GrPorterDuffTest.cpp

index 2538680302e709748f294c9eaebea6fc992485a0..0e065c231f4c0740a54660562fbafcaa52842e07 100644 (file)
@@ -84,6 +84,7 @@ protected:
 
     void addPendingExecution() const {
         this->validate();
+        SkASSERT(fRefCnt > 0);
         if (0 == fPendingExecutions) {
             static_cast<const DERIVED*>(this)->addPendingIOs();
         }
index 8488dc4d5d6555c08fc55580ece09b6e6f82eb23..57314ec7d4da6186e1132ca4025d627f5db382e5 100644 (file)
  * Produced by GrClip. It provides a set of modifications to the drawing state that are used to
  * create the final GrPipeline for a GrOp.
  */
-class GrAppliedClip {
+class GrAppliedClip : public SkNoncopyable {
 public:
-    GrAppliedClip() = default;
-    GrAppliedClip(GrAppliedClip&& that) = default;
-    GrAppliedClip(const GrAppliedClip&) = delete;
-
     const GrScissorState& scissorState() const { return fScissorState; }
     const GrWindowRectsState& windowRectsState() const { return fWindowRectsState; }
     GrFragmentProcessor* clipCoverageFragmentProcessor() const { return fClipCoverageFP.get(); }
@@ -56,32 +52,12 @@ public:
         fHasStencilClip = true;
     }
 
-    bool doesClip() const {
-        return fScissorState.enabled() || fClipCoverageFP || fHasStencilClip ||
-               fWindowRectsState.enabled();
-    }
-
-    bool operator==(const GrAppliedClip& that) const {
-        if (fScissorState != that.fScissorState || fHasStencilClip != that.fHasStencilClip) {
-            return false;
-        }
-        if (SkToBool(fClipCoverageFP)) {
-            if (!SkToBool(that.fClipCoverageFP) ||
-                !that.fClipCoverageFP->isEqual(*fClipCoverageFP)) {
-                return false;
-            }
-        } else if (SkToBool(that.fClipCoverageFP)) {
-            return false;
-        }
-        return fWindowRectsState == that.fWindowRectsState;
-    }
-    bool operator!=(const GrAppliedClip& that) const { return !(*this == that); }
-
 private:
     GrScissorState             fScissorState;
     GrWindowRectsState         fWindowRectsState;
     sk_sp<GrFragmentProcessor> fClipCoverageFP;
     bool                       fHasStencilClip = false;
+    typedef SkNoncopyable INHERITED;
 };
 
 #endif
index c6f5d383832e6ca88d712d7a1cfc708162a17fd1..2dddbba2a23622f9815c3677ae31ed32017db217 100644 (file)
 #include "GrPipeline.h"
 
 GrOpFlushState::GrOpFlushState(GrGpu* gpu, GrResourceProvider* resourceProvider)
-        : fGpu(gpu)
-        , fResourceProvider(resourceProvider)
-        , fCommandBuffer(nullptr)
-        , fVertexPool(gpu)
-        , fIndexPool(gpu)
-        , fLastIssuedToken(GrDrawOpUploadToken::AlreadyFlushedToken())
-        , fLastFlushedToken(0)
-        , fOpArgs(nullptr) {}
+    : fGpu(gpu)
+    , fResourceProvider(resourceProvider)
+    , fCommandBuffer(nullptr)
+    , fVertexPool(gpu)
+    , fIndexPool(gpu)
+    , fLastIssuedToken(GrDrawOpUploadToken::AlreadyFlushedToken())
+    , fLastFlushedToken(0) {}
 
 void* GrOpFlushState::makeVertexSpace(size_t vertexSize, int vertexCount,
                                          const GrBuffer** buffer, int* startVertex) {
index d7ed4e0b47b7699d2f4549d8321da1d3df671ef2..ed77c3b4680d1de67c6610b835bc3093f4e3f69a 100644 (file)
@@ -96,30 +96,22 @@ public:
         fIndexPool.reset();
     }
 
-    /** Additional data required on a per-op basis when executing GrDrawOps. */
-    struct DrawOpArgs {
-        GrRenderTarget* fRenderTarget;
-        const GrAppliedClip* fAppliedClip;
-        GrXferProcessor::DstTexture fDstTexture;
-    };
-
-    void setDrawOpArgs(DrawOpArgs* opArgs) { fOpArgs = opArgs; }
-
-    const DrawOpArgs& drawOpArgs() const {
-        SkASSERT(fOpArgs);
-        return *fOpArgs;
-    }
-
 private:
+
     GrGpu*                                      fGpu;
+
     GrResourceProvider*                         fResourceProvider;
+
     GrGpuCommandBuffer*                         fCommandBuffer;
+
     GrVertexBufferAllocPool                     fVertexPool;
     GrIndexBufferAllocPool                      fIndexPool;
+
     SkSTArray<4, GrDrawOp::DeferredUploadFn>    fAsapUploads;
+
     GrDrawOpUploadToken                         fLastIssuedToken;
+
     GrDrawOpUploadToken                         fLastFlushedToken;
-    DrawOpArgs*                                 fOpArgs;
 };
 
 /**
index 7ab5cbfac6b227d6e3c54ffa76bbeb23cd036a70..845ae4488dba6f51bc5f12e8d62fddd34731c1e2 100644 (file)
@@ -24,31 +24,27 @@ GrPipelineOptimizations GrPipeline::init(const InitArgs& args) {
     SkASSERT(args.fRenderTarget);
 
     fRenderTarget.reset(args.fRenderTarget);
+    fScissorState = args.fAppliedClip->scissorState();
+    fWindowRectsState = args.fAppliedClip->windowRectsState();
+    fUserStencilSettings = args.fUserStencil;
+    fDrawFace = static_cast<int16_t>(args.fDrawFace);
 
     fFlags = args.fFlags;
-    if (args.fAppliedClip) {
-        fScissorState = args.fAppliedClip->scissorState();
-        if (args.fAppliedClip->hasStencilClip()) {
-            fFlags |= kHasStencilClip_Flag;
-        }
-        fWindowRectsState = args.fAppliedClip->windowRectsState();
-    }
     if (args.fProcessors->usesDistanceVectorField()) {
         fFlags |= kUsesDistanceVectorField_Flag;
     }
+    if (args.fAppliedClip->hasStencilClip()) {
+        fFlags |= kHasStencilClip_Flag;
+    }
+    if (!args.fUserStencil->isDisabled(args.fAppliedClip->hasStencilClip())) {
+        fFlags |= kStencilEnabled_Flag;
+    }
     if (args.fProcessors->disableOutputConversionToSRGB()) {
         fFlags |= kDisableOutputConversionToSRGB_Flag;
     }
     if (args.fProcessors->allowSRGBInputs()) {
         fFlags |= kAllowSRGBInputs_Flag;
     }
-    if (!args.fUserStencil->isDisabled(fFlags & kHasStencilClip_Flag)) {
-        fFlags |= kStencilEnabled_Flag;
-    }
-
-    fUserStencilSettings = args.fUserStencil;
-
-    fDrawFace = static_cast<int16_t>(args.fDrawFace);
 
     bool isHWAA = kHWAntialias_Flag & args.fFlags;
 
@@ -90,7 +86,7 @@ GrPipelineOptimizations GrPipeline::init(const InitArgs& args) {
     fNumColorProcessors = args.fProcessors->numColorFragmentProcessors() - colorFPsToEliminate;
     int numTotalProcessors =
             fNumColorProcessors + args.fProcessors->numCoverageFragmentProcessors();
-    if (args.fAppliedClip && args.fAppliedClip->clipCoverageFragmentProcessor()) {
+    if (args.fAppliedClip->clipCoverageFragmentProcessor()) {
         ++numTotalProcessors;
     }
     fFragmentProcessors.reset(numTotalProcessors);
@@ -105,10 +101,8 @@ GrPipelineOptimizations GrPipeline::init(const InitArgs& args) {
         const GrFragmentProcessor* fp = args.fProcessors->coverageFragmentProcessor(i);
         fFragmentProcessors[currFPIdx].reset(fp);
     }
-    if (args.fAppliedClip) {
-        if (const GrFragmentProcessor* fp = args.fAppliedClip->clipCoverageFragmentProcessor()) {
-            fFragmentProcessors[currFPIdx].reset(fp);
-        }
+    if (const GrFragmentProcessor* fp = args.fAppliedClip->clipCoverageFragmentProcessor()) {
+        fFragmentProcessors[currFPIdx].reset(fp);
     }
 
     // Setup info we need to pass to GrPrimitiveProcessors that are used with this GrPipeline.
@@ -124,6 +118,10 @@ GrPipelineOptimizations GrPipeline::init(const InitArgs& args) {
     if (SkToBool(optFlags & GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag)) {
         optimizations.fFlags |= GrPipelineOptimizations::kCanTweakAlphaForCoverage_Flag;
     }
+
+    if (GrXPFactory::WillReadDst(xpFactory, *args.fAnalysis)) {
+        optimizations.fFlags |= GrPipelineOptimizations::kXPReadsDst_Flag;
+    }
     return optimizations;
 }
 
index 4c439433f559c0eb0547287b04f39d6358276c07..f5b8fe9cf0c2f57e330b20065822b900638a4930 100644 (file)
@@ -70,6 +70,11 @@ public:
         return false;
     }
 
+    /**
+     * Returns true if the color written to the output pixel depends on the pixels previous value.
+     */
+    bool xpReadsDst() const { return SkToBool(kXPReadsDst_Flag & fFlags); }
+
 private:
     enum {
         // If this is not set the primitive processor need not produce local coordinates
@@ -82,6 +87,8 @@ private:
         // If this flag is set the GrPrimitiveProcessor must produce fOverrideColor as its
         // output color. If not set fOverrideColor is to be ignored.
         kUseOverrideColor_Flag = 0x4,
+
+        kXPReadsDst_Flag = 0x8,
     };
 
     uint32_t    fFlags;
index 94e200454607fd34dd158105dae1e941ba2d7210..c4b82621d1f8853dd2088b1baed460bcd6e357f8 100644 (file)
@@ -38,44 +38,6 @@ GrProcessorSet::GrProcessorSet(GrPaint&& paint) {
     }
 }
 
-GrProcessorSet::~GrProcessorSet() {
-    if (this->isPendingExecution()) {
-        for (auto fp : fFragmentProcessors) {
-            fp->completedExecution();
-        }
-    } else {
-        for (auto fp : fFragmentProcessors) {
-            fp->unref();
-        }
-    }
-}
-
-void GrProcessorSet::makePendingExecution() {
-    SkASSERT(!(kPendingExecution_Flag & fFlags));
-    fFlags |= kPendingExecution_Flag;
-    for (int i = 0; i < fFragmentProcessors.count(); ++i) {
-        fFragmentProcessors[i]->addPendingExecution();
-        fFragmentProcessors[i]->unref();
-    }
-}
-
-bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
-    if (((fFlags ^ that.fFlags) & ~kPendingExecution_Flag) ||
-        fFragmentProcessors.count() != that.fFragmentProcessors.count() ||
-        fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
-        return false;
-    }
-    for (int i = 0; i < fFragmentProcessors.count(); ++i) {
-        if (!fFragmentProcessors[i]->isEqual(*that.fFragmentProcessors[i])) {
-            return false;
-        }
-    }
-    if (fXPFactory != that.fXPFactory) {
-        return false;
-    }
-    return true;
-}
-
 //////////////////////////////////////////////////////////////////////////////
 
 void GrProcessorSet::FragmentProcessorAnalysis::internalInit(const GrPipelineInput& colorInput,
index 18a52fd9b7eaae83864493075d54ef0218e764d3..8203491435e4b49102cf63292511fb8a4b4461bb 100644 (file)
@@ -20,15 +20,13 @@ class GrProcessorSet : private SkNoncopyable {
 public:
     GrProcessorSet(GrPaint&& paint);
 
-    ~GrProcessorSet();
-
-    /**
-     * If an op is recorded with this processor set then this must be called to ensure pending
-     * reads and writes are propagated to resources referred to by the processors. Otherwise,
-     * data hazards may occur.
-     */
-    void makePendingExecution();
-    bool isPendingExecution() const { return SkToBool(kPendingExecution_Flag & fFlags); }
+    ~GrProcessorSet() {
+        // We are deliberately not using sk_sp here because this will be updated to work with
+        // "pending execution" refs.
+        for (auto fp : fFragmentProcessors) {
+            fp->unref();
+        }
+    }
 
     int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; }
     int numCoverageFragmentProcessors() const {
@@ -52,9 +50,6 @@ public:
     }
     bool allowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); }
 
-    bool operator==(const GrProcessorSet& that) const;
-    bool operator!=(const GrProcessorSet& that) const { return !(*this == that); }
-
     /**
      * This is used to track analysis of color and coverage values through the fragment processors.
      */
@@ -161,8 +156,7 @@ private:
     enum Flags : uint16_t {
         kUseDistanceVectorField_Flag = 0x1,
         kDisableOutputConversionToSRGB_Flag = 0x2,
-        kAllowSRGBInputs_Flag = 0x4,
-        kPendingExecution_Flag = 0x8
+        kAllowSRGBInputs_Flag = 0x4
     };
 
     const GrXPFactory* fXPFactory = nullptr;
index 85e5b74c444da63bedd6d496a2a8ac7e560cc89f..8cc383dc3e1e7578f65309c742f8cb45e24366e5 100644 (file)
@@ -507,17 +507,22 @@ bool GrRenderTargetContext::drawFilledRect(const GrClip& clip,
         return true;
     }
 
-    if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
-        (!ss || ss->isDisabled(false))) {
+    GrAAType aaType;
+
+    if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
         InstancedRendering* ir = this->getOpList()->instancedRendering();
-        std::unique_ptr<GrDrawOp> op = ir->recordRect(croppedRect, viewMatrix, std::move(paint), aa,
-                                                      fInstancedPipelineInfo);
+        std::unique_ptr<GrDrawOp> op = ir->recordRect(croppedRect, viewMatrix, paint.getColor(), aa,
+                                                      fInstancedPipelineInfo, &aaType);
         if (op) {
-            this->addDrawOp(clip, std::move(op));
+            GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
+            if (ss) {
+                pipelineBuilder.setUserStencil(ss);
+            }
+            this->addDrawOp(pipelineBuilder, clip, std::move(op));
             return true;
         }
     }
-    GrAAType aaType = this->decideAAType(aa);
+    aaType = this->decideAAType(aa);
     if (GrAAType::kCoverage == aaType) {
         // The fill path can handle rotation but not skew.
         if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
@@ -806,18 +811,21 @@ void GrRenderTargetContext::fillRectToRect(const GrClip& clip,
     }
 
     AutoCheckFlush acf(this->drawingManager());
+    GrAAType aaType;
 
     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
         InstancedRendering* ir = this->getOpList()->instancedRendering();
-        std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, std::move(paint),
-                                                    croppedLocalRect, aa, fInstancedPipelineInfo));
+        std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
+                                                    croppedLocalRect, aa, fInstancedPipelineInfo,
+                                                    &aaType));
         if (op) {
-            this->addDrawOp(clip, std::move(op));
+            GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
+            this->addDrawOp(pipelineBuilder, clip, std::move(op));
             return;
         }
     }
 
-    GrAAType aaType = this->decideAAType(aa);
+    aaType = this->decideAAType(aa);
     if (GrAAType::kCoverage != aaType) {
         this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect,
                                   &croppedLocalRect, nullptr, nullptr, aaType);
@@ -825,10 +833,10 @@ void GrRenderTargetContext::fillRectToRect(const GrClip& clip,
     }
 
     if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
-        std::unique_ptr<GrMeshDrawOp> op = GrAAFillRectOp::MakeWithLocalRect(
+        std::unique_ptr<GrDrawOp> op = GrAAFillRectOp::MakeWithLocalRect(
                 paint.getColor(), viewMatrix, croppedRect, croppedLocalRect);
         GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
-        this->addMeshDrawOp(pipelineBuilder, clip, std::move(op));
+        this->addDrawOp(pipelineBuilder, clip, std::move(op));
         return;
     }
 
@@ -862,18 +870,21 @@ void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
     }
 
     AutoCheckFlush acf(this->drawingManager());
+    GrAAType aaType;
 
     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
         InstancedRendering* ir = this->getOpList()->instancedRendering();
-        std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, std::move(paint),
-                                                    localMatrix, aa, fInstancedPipelineInfo));
+        std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
+                                                    localMatrix, aa, fInstancedPipelineInfo,
+                                                    &aaType));
         if (op) {
-            this->addDrawOp(clip, std::move(op));
+            GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
+            this->addDrawOp(pipelineBuilder, clip, std::move(op));
             return;
         }
     }
 
-    GrAAType aaType = this->decideAAType(aa);
+    aaType = this->decideAAType(aa);
     if (GrAAType::kCoverage != aaType) {
         this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect, nullptr,
                                   &localMatrix, nullptr, aaType);
@@ -1014,19 +1025,21 @@ void GrRenderTargetContext::drawRRect(const GrClip& origClip,
 
     AutoCheckFlush acf(this->drawingManager());
     const SkStrokeRec stroke = style.strokeRec();
+    GrAAType aaType;
 
     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
         stroke.isFillStyle()) {
         InstancedRendering* ir = this->getOpList()->instancedRendering();
-        std::unique_ptr<GrDrawOp> op(
-                ir->recordRRect(rrect, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
+        std::unique_ptr<GrDrawOp> op(ir->recordRRect(rrect, viewMatrix, paint.getColor(), aa,
+                                                     fInstancedPipelineInfo, &aaType));
         if (op) {
-            this->addDrawOp(*clip, std::move(op));
+            GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
+            this->addDrawOp(pipelineBuilder, *clip, std::move(op));
             return;
         }
     }
 
-    GrAAType aaType = this->decideAAType(aa);
+    aaType = this->decideAAType(aa);
     if (GrAAType::kCoverage == aaType) {
         const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
         std::unique_ptr<GrMeshDrawOp> op =
@@ -1091,18 +1104,21 @@ bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
                                              const SkRRect& origInner) {
     SkASSERT(!origInner.isEmpty());
     SkASSERT(!origOuter.isEmpty());
+    GrAAType aaType;
 
     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
         InstancedRendering* ir = this->getOpList()->instancedRendering();
-        std::unique_ptr<GrDrawOp> op(ir->recordDRRect(
-                origOuter, origInner, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
+        std::unique_ptr<GrDrawOp> op(ir->recordDRRect(origOuter, origInner, viewMatrix,
+                                                      paint.getColor(), aa, fInstancedPipelineInfo,
+                                                      &aaType));
         if (op) {
-            this->addDrawOp(clip, std::move(op));
+            GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
+            this->addDrawOp(pipelineBuilder, clip, std::move(op));
             return true;
         }
     }
 
-    GrAAType aaType = this->decideAAType(aa);
+    aaType = this->decideAAType(aa);
 
     GrPrimitiveEdgeType innerEdgeType, outerEdgeType;
     if (GrAAType::kCoverage == aaType) {
@@ -1239,19 +1255,21 @@ void GrRenderTargetContext::drawOval(const GrClip& clip,
 
     AutoCheckFlush acf(this->drawingManager());
     const SkStrokeRec& stroke = style.strokeRec();
+    GrAAType aaType;
 
     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
         stroke.isFillStyle()) {
         InstancedRendering* ir = this->getOpList()->instancedRendering();
-        std::unique_ptr<GrDrawOp> op(
-                ir->recordOval(oval, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
+        std::unique_ptr<GrDrawOp> op(ir->recordOval(oval, viewMatrix, paint.getColor(), aa,
+                                                    fInstancedPipelineInfo, &aaType));
         if (op) {
-            this->addDrawOp(clip, std::move(op));
+            GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
+            this->addDrawOp(pipelineBuilder, clip, std::move(op));
             return;
         }
     }
 
-    GrAAType aaType = this->decideAAType(aa);
+    aaType = this->decideAAType(aa);
     if (GrAAType::kCoverage == aaType) {
         const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
         std::unique_ptr<GrMeshDrawOp> op =
@@ -1655,60 +1673,21 @@ static void op_bounds(SkRect* bounds, const GrOp* op) {
     }
 }
 
-uint32_t GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op) {
-    ASSERT_SINGLE_OWNER
-    if (this->drawingManager()->wasAbandoned()) {
-        return SK_InvalidUniqueID;
-    }
-    SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addDrawOp");
-
-    // Setup clip
-    SkRect bounds;
-    op_bounds(&bounds, op.get());
-    GrAppliedClip appliedClip;
-    GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
-    if (!clip.apply(fContext, this, fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA,
-                    fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil, &appliedClip,
-                    &bounds)) {
-        return SK_InvalidUniqueID;
-    }
-
-    // This forces instantiation of the render target.
-    GrRenderTarget* rt = this->accessRenderTarget();
-    if (!rt) {
-        return SK_InvalidUniqueID;
-    }
-
-    if (fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil ||
-        appliedClip.hasStencilClip()) {
-        if (!fContext->resourceProvider()->attachStencilAttachment(rt)) {
-            SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
-            return SK_InvalidUniqueID;
-        }
-    }
-
-    GrXferProcessor::DstTexture dstTexture;
-    if (op->xpRequiresDstTexture(*this->caps(), &appliedClip)) {
-        this->setupDstTexture(rt, clip, op->bounds(), &dstTexture);
-        if (!dstTexture.texture()) {
-            return SK_InvalidUniqueID;
-        }
-    }
-
-    op->setClippedBounds(bounds);
-    return this->getOpList()->addOp(std::move(op), this, std::move(appliedClip), dstTexture);
-}
-
 uint32_t GrRenderTargetContext::addMeshDrawOp(const GrPipelineBuilder& pipelineBuilder,
                                               const GrClip& clip,
                                               std::unique_ptr<GrMeshDrawOp> op) {
+    return this->addDrawOp(pipelineBuilder, clip, std::move(op));
+}
+
+uint32_t GrRenderTargetContext::addDrawOp(const GrPipelineBuilder& pipelineBuilder,
+                                          const GrClip& clip,
+                                          std::unique_ptr<GrDrawOp> op) {
     ASSERT_SINGLE_OWNER
     if (this->drawingManager()->wasAbandoned()) {
         return SK_InvalidUniqueID;
     }
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addMeshDrawOp");
+    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addDrawOp");
 
     // Setup clip
     SkRect bounds;
index 8b07c22bd2ca895debf37e0a6798168e42689caa..c6793d3a82c3c5c551a43d5b486bfaa84aca311c 100644 (file)
@@ -22,8 +22,8 @@ class GrClip;
 class GrDrawingManager;
 class GrDrawOp;
 class GrFixedClip;
-class GrMeshDrawOp;
 class GrPipelineBuilder;
+class GrMeshDrawOp;
 class GrRenderTarget;
 class GrRenderTargetContextPriv;
 class GrRenderTargetOpList;
@@ -478,8 +478,9 @@ private:
     // These perform processing specific to Gr[Mesh]DrawOp-derived ops before recording them into
     // the op list. They return the id of the opList to which the op was added, or 0, if it was
     // dropped (e.g., due to clipping).
-    uint32_t addDrawOp(const GrClip&, std::unique_ptr<GrDrawOp>);
-    uint32_t addMeshDrawOp(const GrPipelineBuilder&, const GrClip&, std::unique_ptr<GrMeshDrawOp>);
+    uint32_t addDrawOp(const GrPipelineBuilder&, const GrClip&, std::unique_ptr<GrDrawOp>);
+    uint32_t addMeshDrawOp(const GrPipelineBuilder&, const GrClip&,
+                           std::unique_ptr<GrMeshDrawOp> op);
 
     // Makes a copy of the dst if it is necessary for the draw and returns the texture that should
     // be used by GrXferProcessor to access the destination color. If the texture is nullptr then
index 1a9452f7245baaf0c9289b74e60997b2a187bce9..1c9835389e733ef5a6bc994baa3afc9e8d89af70 100644 (file)
@@ -30,12 +30,10 @@ static const int kDefaultMaxOpLookahead = 10;
 GrRenderTargetOpList::GrRenderTargetOpList(GrRenderTargetProxy* rtp, GrGpu* gpu,
                                            GrResourceProvider* resourceProvider,
                                            GrAuditTrail* auditTrail, const Options& options)
-        : INHERITED(rtp, auditTrail)
-        , fGpu(SkRef(gpu))
-        , fResourceProvider(resourceProvider)
-        , fLastClipStackGenID(SK_InvalidUniqueID)
-        , fClipAllocator(fClipAllocatorStorage, sizeof(fClipAllocatorStorage),
-                         sizeof(fClipAllocatorStorage)) {
+    : INHERITED(rtp, auditTrail)
+    , fGpu(SkRef(gpu))
+    , fResourceProvider(resourceProvider)
+    , fLastClipStackGenID(SK_InvalidUniqueID) {
 
     fMaxOpLookback = (options.fMaxOpCombineLookback < 0) ? kDefaultMaxOpLookback
                                                          : options.fMaxOpCombineLookback;
@@ -84,17 +82,7 @@ void GrRenderTargetOpList::prepareOps(GrOpFlushState* flushState) {
     // Loop over the ops that haven't yet been prepared.
     for (int i = 0; i < fRecordedOps.count(); ++i) {
         if (fRecordedOps[i].fOp) {
-            GrOpFlushState::DrawOpArgs opArgs;
-            if (fRecordedOps[i].fRenderTarget) {
-                opArgs = {
-                    fRecordedOps[i].fRenderTarget.get(),
-                    fRecordedOps[i].fAppliedClip,
-                    fRecordedOps[i].fDstTexture
-                };
-            }
-            flushState->setDrawOpArgs(&opArgs);
             fRecordedOps[i].fOp->prepare(flushState);
-            flushState->setDrawOpArgs(nullptr);
         }
     }
 
@@ -134,17 +122,7 @@ bool GrRenderTargetOpList::executeOps(GrOpFlushState* flushState) {
             }
             flushState->setCommandBuffer(commandBuffer.get());
         }
-        GrOpFlushState::DrawOpArgs opArgs;
-        if (fRecordedOps[i].fRenderTarget) {
-            opArgs = {
-                fRecordedOps[i].fRenderTarget.get(),
-                fRecordedOps[i].fAppliedClip,
-                fRecordedOps[i].fDstTexture
-            };
-            flushState->setDrawOpArgs(&opArgs);
-        }
         fRecordedOps[i].fOp->execute(flushState);
-        flushState->setDrawOpArgs(nullptr);
     }
     if (commandBuffer) {
         commandBuffer->end();
@@ -235,33 +213,8 @@ static inline bool can_reorder(const SkRect& a, const SkRect& b) {
            b.fRight <= a.fLeft || b.fBottom <= a.fTop;
 }
 
-bool GrRenderTargetOpList::combineIfPossible(const RecordedOp& a, GrOp* b,
-                                             const GrAppliedClip* bClip,
-                                             const DstTexture* bDstTexture) {
-    if (a.fAppliedClip) {
-        if (!bClip) {
-            return false;
-        }
-        if (*a.fAppliedClip != *bClip) {
-            return false;
-        }
-    } else if (bClip) {
-        return false;
-    }
-    if (bDstTexture) {
-        if (a.fDstTexture != *bDstTexture) {
-            return false;
-        }
-    } else if (a.fDstTexture.texture()) {
-        return false;
-    }
-    return a.fOp->combineIfPossible(b, *this->caps());
-}
-
 GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr<GrOp> op,
-                                     GrRenderTargetContext* renderTargetContext,
-                                     GrAppliedClip* clip,
-                                     const DstTexture* dstTexture) {
+                                     GrRenderTargetContext* renderTargetContext) {
     GrRenderTarget* renderTarget =
             renderTargetContext ? renderTargetContext->accessRenderTarget()
                                 : nullptr;
@@ -296,7 +249,7 @@ GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr<GrOp> op,
                           candidate.fOp->uniqueID());
                 break;
             }
-            if (this->combineIfPossible(candidate, op.get(), clip, dstTexture)) {
+            if (candidate.fOp->combineIfPossible(op.get(), *this->caps())) {
                 GrOP_INFO("\t\tCombining with (%s, B%u)\n", candidate.fOp->name(),
                           candidate.fOp->uniqueID());
                 GrOP_INFO("\t\t\tCombined op info:\n");
@@ -320,10 +273,7 @@ GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr<GrOp> op,
         GrOP_INFO("\t\tFirstOp\n");
     }
     GR_AUDIT_TRAIL_OP_RESULT_NEW(fAuditTrail, op);
-    if (clip) {
-        clip = fClipAllocator.make<GrAppliedClip>(std::move(*clip));
-    }
-    fRecordedOps.emplace_back(std::move(op), renderTarget, clip, dstTexture);
+    fRecordedOps.emplace_back(std::move(op), renderTarget);
     fRecordedOps.back().fOp->wasRecorded();
     fLastFullClearOp = nullptr;
     fLastFullClearRenderTargetID.makeInvalid();
@@ -356,10 +306,9 @@ void GrRenderTargetOpList::forwardCombine() {
                 // via backwards combining in recordOp.
 
                 // not sure why this fires with device-clipping in gm/complexclip4.cpp
-                SkASSERT(!this->combineIfPossible(fRecordedOps[i], candidate.fOp.get(),
-                                                  candidate.fAppliedClip, &candidate.fDstTexture));
-            } else if (this->combineIfPossible(fRecordedOps[i], candidate.fOp.get(),
-                                               candidate.fAppliedClip, &candidate.fDstTexture)) {
+//                SkASSERT(!op->combineIfPossible(candidate.fOp.get(), *this->caps()));
+
+            } else if (op->combineIfPossible(candidate.fOp.get(), *this->caps())) {
                 GrOP_INFO("\t\tCombining with (%s, B%u)\n", candidate.fOp->name(),
                           candidate.fOp->uniqueID());
                 GR_AUDIT_TRAIL_OPS_RESULT_COMBINED(fAuditTrail, op, candidate.fOp.get());
index 976b271d1c090df97c697e3a5ca764e8374583b4..f4458b57754696c707174ee563ff4b65a56cc4e3 100644 (file)
@@ -8,11 +8,9 @@
 #ifndef GrRenderTargetOpList_DEFINED
 #define GrRenderTargetOpList_DEFINED
 
-#include "GrAppliedClip.h"
 #include "GrOpList.h"
-#include "GrPathRendering.h"
 #include "GrPrimitiveProcessor.h"
-#include "SkArenaAlloc.h"
+#include "GrPathRendering.h"
 #include "SkClipStack.h"
 #include "SkMatrix.h"
 #include "SkStringUtils.h"
 class GrAuditTrail;
 class GrClearOp;
 class GrCaps;
+class GrClip;
 class GrOp;
 class GrPipelineBuilder;
 class GrRenderTargetProxy;
 
 class GrRenderTargetOpList final : public GrOpList {
-private:
-    using DstTexture = GrXferProcessor::DstTexture;
-
 public:
     /** Options for GrRenderTargetOpList behavior. */
     struct Options {
@@ -72,13 +68,7 @@ public:
     const GrCaps* caps() const { return fGpu->caps(); }
 
     uint32_t addOp(std::unique_ptr<GrOp> op, GrRenderTargetContext* renderTargetContext) {
-        this->recordOp(std::move(op), renderTargetContext, nullptr, nullptr);
-        return this->uniqueID();
-    }
-    uint32_t addOp(std::unique_ptr<GrOp> op, GrRenderTargetContext* renderTargetContext,
-                   GrAppliedClip&& clip, const DstTexture& dstTexture) {
-        this->recordOp(std::move(op), renderTargetContext, clip.doesClip() ? &clip : nullptr,
-                       &dstTexture);
+        this->recordOp(std::move(op), renderTargetContext);
         return this->uniqueID();
     }
 
@@ -115,34 +105,23 @@ public:
 private:
     friend class GrRenderTargetContextPriv; // for clearStencilClip and stencil clip state.
 
-    struct RecordedOp {
-        RecordedOp(std::unique_ptr<GrOp> op, GrRenderTarget* rt, const GrAppliedClip* appliedClip,
-                   const DstTexture* dstTexture)
-                : fOp(std::move(op)), fRenderTarget(rt), fAppliedClip(appliedClip) {
-            if (dstTexture) {
-                fDstTexture = *dstTexture;
-            }
-        }
-        std::unique_ptr<GrOp> fOp;
-        // TODO: These ops will all to target the same render target and this won't be needed.
-        GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget;
-        DstTexture fDstTexture;
-        const GrAppliedClip* fAppliedClip;
-    };
-
     // If the input op is combined with an earlier op, this returns the combined op. Otherwise, it
     // returns the input op.
-    GrOp* recordOp(std::unique_ptr<GrOp>, GrRenderTargetContext*, GrAppliedClip* = nullptr,
-                   const DstTexture* = nullptr);
+    GrOp* recordOp(std::unique_ptr<GrOp>, GrRenderTargetContext*);
 
     void forwardCombine();
 
     // Used only via GrRenderTargetContextPriv.
     void clearStencilClip(const GrFixedClip&, bool insideStencilMask, GrRenderTargetContext*);
 
-    // If this returns true then b has been merged into a's op.
-    bool combineIfPossible(const RecordedOp& a, GrOp* b, const GrAppliedClip* bClip,
-                           const DstTexture* bDstTexture);
+    struct RecordedOp {
+        RecordedOp(std::unique_ptr<GrOp> op, GrRenderTarget* rt)
+                : fOp(std::move(op)), fRenderTarget(rt) {}
+        std::unique_ptr<GrOp> fOp;
+        // TODO: These ops will all to target the same render target and this won't be needed.
+        GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget;
+    };
+    SkSTArray<256, RecordedOp, true> fRecordedOps;
 
     GrClearOp* fLastFullClearOp = nullptr;
     GrGpuResource::UniqueID fLastFullClearRenderTargetID = GrGpuResource::UniqueID::InvalidID();
@@ -158,11 +137,6 @@ private:
     int32_t fLastClipStackGenID;
     SkIRect fLastDevClipBounds;
 
-    SkSTArray<256, RecordedOp, true> fRecordedOps;
-
-    char fClipAllocatorStorage[4096];
-    SkArenaAlloc fClipAllocator;
-
     typedef GrOpList INHERITED;
 };
 
index 8a0bc1a6382e3b13aedfc2185c4543f3c70f371b..d70daa2c79b0ffa761288a32b9596f0d3bbc08af 100644 (file)
@@ -54,7 +54,6 @@ void GrTextureOpList::prepareOps(GrOpFlushState* flushState) {
     // Loop over the ops that haven't yet generated their geometry
     for (int i = 0; i < fRecordedOps.count(); ++i) {
         if (fRecordedOps[i]) {
-            // We do not call flushState->setDrawOpArgs as this op list does not support GrDrawOps.
             fRecordedOps[i]->prepare(flushState);
         }
     }
@@ -66,7 +65,6 @@ bool GrTextureOpList::executeOps(GrOpFlushState* flushState) {
     }
 
     for (int i = 0; i < fRecordedOps.count(); ++i) {
-        // We do not call flushState->setDrawOpArgs as this op list does not support GrDrawOps.
         fRecordedOps[i]->execute(flushState);
     }
 
index 32ab45c65e79b9572af0b3eeb3ada0bf7719e133..4d877d6b270fbd5bca8ccdaeb92b7844436f28c6 100644 (file)
@@ -176,6 +176,14 @@ SkString GrXferProcessor::BlendInfo::dump() const {
 
 ///////////////////////////////////////////////////////////////////////////////
 
+bool GrXPFactory::WillReadDst(const GrXPFactory* factory,
+                              const GrProcessorSet::FragmentProcessorAnalysis& analysis) {
+    if (factory) {
+        return factory->willReadsDst(analysis);
+    }
+    return GrPorterDuffXPFactory::WillSrcOverReadDst(analysis);
+}
+
 bool GrXPFactory::WillNeedDstTexture(const GrXPFactory* factory, const GrCaps& caps,
                                      const GrProcessorSet::FragmentProcessorAnalysis& analysis) {
     bool result;
@@ -185,6 +193,7 @@ bool GrXPFactory::WillNeedDstTexture(const GrXPFactory* factory, const GrCaps& c
     } else {
         result = GrPorterDuffXPFactory::WillSrcOverNeedDstTexture(caps, analysis);
     }
+    SkASSERT(!(result && !WillReadDst(factory, analysis)));
     return result;
 }
 
@@ -195,14 +204,6 @@ bool GrXPFactory::CompatibleWithCoverageAsAlpha(const GrXPFactory* factory, bool
     return GrPorterDuffXPFactory::SrcOverIsCompatibleWithCoverageAsAlpha();
 }
 
-bool GrXPFactory::CanCombineOverlappedStencilAndCover(const GrXPFactory* factory,
-                                                      bool colorIsOpaque) {
-    if (factory) {
-        return factory->canCombineOverlappedStencilAndCover(colorIsOpaque);
-    }
-    return GrPorterDuffXPFactory::SrcOverCanCombineOverlappedStencilAndCover(colorIsOpaque);
-}
-
 GrXferProcessor* GrXPFactory::createXferProcessor(const FragmentProcessorAnalysis& analysis,
                                                   bool hasMixedSamples,
                                                   const DstTexture* dstTexture,
index 35ce5fa4a214a5e0c061168e012743af2ea221dc..7f3fd30e8daff8f9b58ed1953047559a07f3aee8 100644 (file)
@@ -65,7 +65,9 @@ public:
         }
 
         DstTexture(GrTexture* texture, const SkIPoint& offset)
-                : fTexture(SkSafeRef(texture)), fOffset(texture ? offset : SkIPoint{0, 0}) {}
+            : fTexture(SkSafeRef(texture))
+            , fOffset(offset) {
+        }
 
         DstTexture& operator=(const DstTexture& other) {
             fTexture = other.fTexture;
@@ -73,11 +75,6 @@ public:
             return *this;
         }
 
-        bool operator==(const DstTexture& that) const {
-            return fTexture == that.fTexture && fOffset == that.fOffset;
-        }
-        bool operator!=(const DstTexture& that) const { return !(*this == that); }
-
         const SkIPoint& offset() const { return fOffset; }
 
         void setOffset(const SkIPoint& offset) { fOffset = offset; }
@@ -87,9 +84,6 @@ public:
 
         void setTexture(sk_sp<GrTexture> texture) {
             fTexture = std::move(texture);
-            if (!fTexture) {
-                fOffset = {0, 0};
-            }
         }
 
     private:
@@ -306,6 +300,11 @@ public:
                                          const DstTexture*,
                                          const GrCaps& caps) const;
 
+    /**
+     * Is the destination color required either in the shader or fixed function blending.
+     */
+    static bool WillReadDst(const GrXPFactory*, const FragmentProcessorAnalysis&);
+
     /**
     * This will return true if the xfer processor needs the dst color in the shader and the way
     * that the color will be made available to the xfer processor is by sampling a texture.
@@ -316,17 +315,13 @@ public:
 
     static bool CompatibleWithCoverageAsAlpha(const GrXPFactory*, bool colorIsOpaque);
 
-    /**
-     * This indicates whether the the xfer processor will produce the same bleneded color result
-     * if a series of overlapping stencil and cover operations are replaced by a series of stencil
-     * operations and a single cover. A uniform src color is assumed.
-     **/
-    static bool CanCombineOverlappedStencilAndCover(const GrXPFactory*, bool colorIsOpaque);
-
 protected:
     constexpr GrXPFactory() {}
 
 private:
+    /** Subclass-specific implementation of WillReadDst(). */
+    virtual bool willReadsDst(const FragmentProcessorAnalysis& pipelineAnalysis) const = 0;
+
     virtual GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
                                                    const FragmentProcessorAnalysis&,
                                                    bool hasMixedSamples,
@@ -339,7 +334,6 @@ private:
     virtual bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const = 0;
 
     virtual bool compatibleWithCoverageAsAlpha(bool colorIsOpaque) const = 0;
-    virtual bool canCombineOverlappedStencilAndCover(bool colorIsOpaque) const { return false; }
 };
 #if defined(__GNUC__) || defined(__clang)
 #pragma GCC diagnostic pop
index 184ef4e56ce02448823610d65f85f7734aa65810..807a2b0fc6c613807195b368286e2b15bd34c9e9 100644 (file)
@@ -32,6 +32,10 @@ public:
 private:
     constexpr GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage);
 
+    bool willReadsDst(const FragmentProcessorAnalysis&) const override {
+        return fRegionOp != SkRegion::kReplace_Op;
+    }
+
     GrXferProcessor* onCreateXferProcessor(const GrCaps&,
                                            const FragmentProcessorAnalysis&,
                                            bool hasMixedSamples,
index 37e4c167657d338882f3ea00df10a19e6490d4ba..31c42ebfd79a99af376be8d18a63d21adea65e10 100644 (file)
@@ -327,6 +327,8 @@ private:
                                            bool hasMixedSamples,
                                            const DstTexture*) const override;
 
+    bool willReadsDst(const FragmentProcessorAnalysis&) const override { return true; }
+
     bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override;
 
     bool compatibleWithCoverageAsAlpha(bool colorIsOpaque) const override { return true; }
index 78442f412554089f955a4453f5a2937c14fd4955..f9206f7c1983a1bdc3e250aa091ebb69fb662cc8 100644 (file)
@@ -24,6 +24,8 @@ public:
     static const GrXPFactory* Get();
 
 private:
+    bool willReadsDst(const FragmentProcessorAnalysis&) const override { return false; }
+
     constexpr GrDisableColorXPFactory() {}
 
     bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override {
index f98435515a8132eb01fe9c7c78f0e99983d4bdb6..8b35bb996a9ab3a0d7e50309845b86b7d4e31c0d 100644 (file)
@@ -759,11 +759,10 @@ GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor(
     return new PorterDuffXferProcessor(blendFormula);
 }
 
-bool GrPorterDuffXPFactory::canCombineOverlappedStencilAndCover(bool colorIsOpaque) const {
-    // Ignore the effect of coverage here.
-    BlendFormula colorFormula = gBlendTable[colorIsOpaque][0][(int)fBlendMode];
+bool GrPorterDuffXPFactory::willReadsDst(const FragmentProcessorAnalysis& analysis) const {
+    BlendFormula colorFormula = gBlendTable[analysis.isOutputColorOpaque()][0][(int)fBlendMode];
     SkASSERT(kAdd_GrBlendEquation == colorFormula.fBlendEquation);
-    return !colorFormula.usesDstColor();
+    return (colorFormula.usesDstColor() || analysis.hasCoverage());
 }
 
 bool GrPorterDuffXPFactory::willReadDstInShader(const GrCaps& caps,
@@ -870,6 +869,10 @@ sk_sp<GrXferProcessor> GrPorterDuffXPFactory::CreateNoCoverageXP(SkBlendMode ble
     return sk_make_sp<PorterDuffXferProcessor>(formula);
 }
 
+bool GrPorterDuffXPFactory::WillSrcOverReadDst(const FragmentProcessorAnalysis& analysis) {
+    return analysis.hasCoverage() || !analysis.isOutputColorOpaque();
+}
+
 bool GrPorterDuffXPFactory::WillSrcOverNeedDstTexture(const GrCaps& caps,
                                                       const FragmentProcessorAnalysis& analysis) {
     if (caps.shaderCaps()->dstReadInShaderSupport() ||
index 719bd18527ef9eea8d8fd03b0a6e9463324a54f4..dd790e84314dacd63ed34dbc98a22a96f802f6d1 100644 (file)
@@ -37,16 +37,14 @@ public:
         by reference because it is global and its ref-cnting methods are not thread safe. */
     static const GrXferProcessor& SimpleSrcOverXP();
 
+    static bool WillSrcOverReadDst(const FragmentProcessorAnalysis& analysis);
     static bool WillSrcOverNeedDstTexture(const GrCaps&, const FragmentProcessorAnalysis&);
     static bool SrcOverIsCompatibleWithCoverageAsAlpha() { return true; }
-    static bool SrcOverCanCombineOverlappedStencilAndCover(bool colorIsOpaque) {
-        return colorIsOpaque;
-    }
 
 private:
     constexpr GrPorterDuffXPFactory(SkBlendMode);
 
-    bool canCombineOverlappedStencilAndCover(bool colorIsOpaque) const override;
+    bool willReadsDst(const FragmentProcessorAnalysis&) const override;
 
     GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
                                            const FragmentProcessorAnalysis&,
index bfdb9601f9240e124dc7d5a6f2e3c4d152e4ff40..0d2a2ddb9c7d27c5bc5185dc0c5db1a08dcab9b5 100644 (file)
@@ -19,8 +19,7 @@ class GLInstancedRendering::GLOp final : public InstancedRendering::Op {
 public:
     DEFINE_OP_CLASS_ID
 
-    GLOp(GLInstancedRendering* instRendering, GrPaint&& paint)
-            : INHERITED(ClassID(), std::move(paint), instRendering) {}
+    GLOp(GLInstancedRendering* instRendering) : INHERITED(ClassID(), instRendering) {}
     int numGLCommands() const { return 1 + fNumChangesInGeometry; }
 
 private:
@@ -61,8 +60,8 @@ inline GrGLGpu* GLInstancedRendering::glGpu() const {
     return static_cast<GrGLGpu*>(this->gpu());
 }
 
-std::unique_ptr<InstancedRendering::Op> GLInstancedRendering::makeOp(GrPaint&& paint) {
-    return std::unique_ptr<Op>(new GLOp(this, std::move(paint)));
+std::unique_ptr<InstancedRendering::Op> GLInstancedRendering::makeOp() {
+    return std::unique_ptr<Op>(new GLOp(this));
 }
 
 void GLInstancedRendering::onBeginFlush(GrResourceProvider* rp) {
index d1affba2bd5da05d65e11a7df13944809550c46e..0088217bb29efe02fd131cbee08cc20649fe3c8c 100644 (file)
@@ -33,7 +33,7 @@ private:
 
     GrGLGpu* glGpu() const;
 
-    std::unique_ptr<Op> makeOp(GrPaint&& paint) override;
+    std::unique_ptr<Op> makeOp() override;
 
     void onBeginFlush(GrResourceProvider*) override;
     void onDraw(const GrPipeline&, const InstanceProcessor&, const Op*) override;
index 179552c852ca1fc7a78c142b1c8207554455a6cf..ef2264b0eff11e7a096d70ed350f2b96bdce579e 100644 (file)
@@ -22,31 +22,32 @@ InstancedRendering::InstancedRendering(GrGpu* gpu)
 }
 
 std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect,
-                                                         const SkMatrix& viewMatrix,
-                                                         GrPaint&& paint, GrAA aa,
-                                                         const GrInstancedPipelineInfo& info) {
-    return this->recordShape(ShapeType::kRect, rect, viewMatrix, std::move(paint), rect, aa, info);
+                                                         const SkMatrix& viewMatrix, GrColor color,
+                                                         GrAA aa,
+                                                         const GrInstancedPipelineInfo& info,
+                                                         GrAAType* aaType) {
+    return this->recordShape(ShapeType::kRect, rect, viewMatrix, color, rect, aa, info, aaType);
 }
 
 std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect,
-                                                         const SkMatrix& viewMatrix,
-                                                         GrPaint&& paint, const SkRect& localRect,
-                                                         GrAA aa,
-                                                         const GrInstancedPipelineInfo& info) {
-    return this->recordShape(ShapeType::kRect, rect, viewMatrix, std::move(paint), localRect, aa,
-                             info);
+                                                         const SkMatrix& viewMatrix, GrColor color,
+                                                         const SkRect& localRect, GrAA aa,
+                                                         const GrInstancedPipelineInfo& info,
+                                                         GrAAType* aaType) {
+    return this->recordShape(ShapeType::kRect, rect, viewMatrix, color, localRect, aa, info,
+                             aaType);
 }
 
 std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect,
-                                                         const SkMatrix& viewMatrix,
-                                                         GrPaint&& paint,
+                                                         const SkMatrix& viewMatrix, GrColor color,
                                                          const SkMatrix& localMatrix, GrAA aa,
-                                                         const GrInstancedPipelineInfo& info) {
+                                                         const GrInstancedPipelineInfo& info,
+                                                         GrAAType* aaType) {
     if (localMatrix.hasPerspective()) {
         return nullptr; // Perspective is not yet supported in the local matrix.
     }
-    if (std::unique_ptr<Op> op = this->recordShape(ShapeType::kRect, rect, viewMatrix,
-                                                   std::move(paint), rect, aa, info)) {
+    if (std::unique_ptr<Op> op = this->recordShape(ShapeType::kRect, rect, viewMatrix, color, rect,
+                                                   aa, info, aaType)) {
         op->getSingleInstance().fInfo |= kLocalMatrix_InfoFlag;
         op->appendParamsTexel(localMatrix.getScaleX(), localMatrix.getSkewX(),
                               localMatrix.getTranslateX());
@@ -59,39 +60,39 @@ std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect,
 }
 
 std::unique_ptr<GrDrawOp> InstancedRendering::recordOval(const SkRect& oval,
-                                                         const SkMatrix& viewMatrix,
-                                                         GrPaint&& paint, GrAA aa,
-                                                         const GrInstancedPipelineInfo& info) {
-    return this->recordShape(ShapeType::kOval, oval, viewMatrix, std::move(paint), oval, aa, info);
+                                                         const SkMatrix& viewMatrix, GrColor color,
+                                                         GrAA aa,
+                                                         const GrInstancedPipelineInfo& info,
+                                                         GrAAType* aaType) {
+    return this->recordShape(ShapeType::kOval, oval, viewMatrix, color, oval, aa, info, aaType);
 }
 
 std::unique_ptr<GrDrawOp> InstancedRendering::recordRRect(const SkRRect& rrect,
-                                                          const SkMatrix& viewMatrix,
-                                                          GrPaint&& paint, GrAA aa,
-                                                          const GrInstancedPipelineInfo& info) {
+                                                          const SkMatrix& viewMatrix, GrColor color,
+                                                          GrAA aa,
+                                                          const GrInstancedPipelineInfo& info,
+                                                          GrAAType* aaType) {
     if (std::unique_ptr<Op> op =
-                this->recordShape(GetRRectShapeType(rrect), rrect.rect(), viewMatrix,
-                                  std::move(paint), rrect.rect(), aa, info)) {
+                this->recordShape(GetRRectShapeType(rrect), rrect.rect(), viewMatrix, color,
+                                  rrect.rect(), aa, info, aaType)) {
         op->appendRRectParams(rrect);
         return std::move(op);
     }
     return nullptr;
 }
 
-std::unique_ptr<GrDrawOp> InstancedRendering::recordDRRect(const SkRRect& outer,
-                                                           const SkRRect& inner,
-                                                           const SkMatrix& viewMatrix,
-                                                           GrPaint&& paint, GrAA aa,
-                                                           const GrInstancedPipelineInfo& info) {
+std::unique_ptr<GrDrawOp> InstancedRendering::recordDRRect(
+        const SkRRect& outer, const SkRRect& inner, const SkMatrix& viewMatrix, GrColor color,
+        GrAA aa, const GrInstancedPipelineInfo& info, GrAAType* aaType) {
     if (inner.getType() > SkRRect::kSimple_Type) {
        return nullptr; // Complex inner round rects are not yet supported.
     }
     if (SkRRect::kEmpty_Type == inner.getType()) {
-        return this->recordRRect(outer, viewMatrix, std::move(paint), aa, info);
+        return this->recordRRect(outer, viewMatrix, color, aa, info, aaType);
     }
     if (std::unique_ptr<Op> op =
-                this->recordShape(GetRRectShapeType(outer), outer.rect(), viewMatrix,
-                                  std::move(paint), outer.rect(), aa, info)) {
+                this->recordShape(GetRRectShapeType(outer), outer.rect(), viewMatrix, color,
+                                  outer.rect(), aa, info, aaType)) {
         op->appendRRectParams(outer);
         ShapeType innerShapeType = GetRRectShapeType(inner);
         op->fInfo.fInnerShapeTypes |= GetShapeFlag(innerShapeType);
@@ -104,31 +105,28 @@ std::unique_ptr<GrDrawOp> InstancedRendering::recordDRRect(const SkRRect& outer,
 }
 
 std::unique_ptr<InstancedRendering::Op> InstancedRendering::recordShape(
-        ShapeType type, const SkRect& bounds, const SkMatrix& viewMatrix, GrPaint&& paint,
-        const SkRect& localRect, GrAA aa, const GrInstancedPipelineInfo& info) {
+        ShapeType type, const SkRect& bounds, const SkMatrix& viewMatrix, GrColor color,
+        const SkRect& localRect, GrAA aa, const GrInstancedPipelineInfo& info, GrAAType* aaType) {
     SkASSERT(State::kRecordingDraws == fState);
 
     if (info.fIsRenderingToFloat && fGpu->caps()->avoidInstancedDrawsToFPTargets()) {
         return nullptr;
     }
 
-    GrAAType aaType;
-    if (!this->selectAntialiasMode(viewMatrix, aa, info, &aaType)) {
+    if (!this->selectAntialiasMode(viewMatrix, aa, info, aaType)) {
         return nullptr;
     }
 
-    GrColor color = paint.getColor();
-    std::unique_ptr<Op> op = this->makeOp(std::move(paint));
-    op->fInfo.setAAType(aaType);
+    std::unique_ptr<Op> op = this->makeOp();
+    op->fInfo.setAAType(*aaType);
     op->fInfo.fShapeTypes = GetShapeFlag(type);
     op->fInfo.fCannotDiscard = true;
-    op->fDrawColorsAreOpaque = GrColorIsOpaque(color);
-    op->fDrawColorsAreSame = true;
+
     Instance& instance = op->getSingleInstance();
     instance.fInfo = (int)type << kShapeType_InfoBit;
 
     Op::HasAABloat aaBloat =
-            (aaType == GrAAType::kCoverage) ? Op::HasAABloat::kYes : Op::HasAABloat::kNo;
+            (*aaType == GrAAType::kCoverage) ? Op::HasAABloat::kYes : Op::HasAABloat::kNo;
     Op::IsZeroArea zeroArea = (bounds.isEmpty()) ? Op::IsZeroArea::kYes : Op::IsZeroArea::kNo;
 
     // The instanced shape renderer draws rectangles of [-1, -1, +1, +1], so we find the matrix that
@@ -231,10 +229,9 @@ inline bool InstancedRendering::selectAntialiasMode(const SkMatrix& viewMatrix,
     return false;
 }
 
-InstancedRendering::Op::Op(uint32_t classID, GrPaint&& paint, InstancedRendering* ir)
+InstancedRendering::Op::Op(uint32_t classID, InstancedRendering* ir)
         : INHERITED(classID)
         , fInstancedRendering(ir)
-        , fProcessors(std::move(paint))
         , fIsTracked(false)
         , fNumDraws(1)
         , fNumChangesInGeometry(0) {
@@ -332,17 +329,20 @@ void InstancedRendering::Op::appendParamsTexel(SkScalar x, SkScalar y, SkScalar
     fInfo.fHasParams = true;
 }
 
-bool InstancedRendering::Op::xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) {
-    GrProcessorSet::FragmentProcessorAnalysis analysis;
-    GrPipelineInput coverageInput;
+void InstancedRendering::Op::getFragmentProcessorAnalysisInputs(
+        FragmentProcessorAnalysisInputs* input) const {
+    input->colorInput()->setToConstant(this->getSingleInstance().fColor);
+
     if (GrAAType::kCoverage == fInfo.aaType() ||
         (GrAAType::kNone == fInfo.aaType() && !fInfo.isSimpleRects() && fInfo.fCannotDiscard)) {
-        coverageInput = GrPipelineInput();
+        input->coverageInput()->setToUnknown();
     } else {
-        coverageInput = GrColor_WHITE;
+        input->coverageInput()->setToSolidCoverage();
     }
-    analysis.init(this->getSingleInstance().fColor, coverageInput, fProcessors, clip, caps);
+}
 
+void InstancedRendering::Op::applyPipelineOptimizations(
+        const GrPipelineOptimizations& optimizations) {
     Draw& draw = this->getSingleDraw(); // This will assert if we have > 1 command.
     SkASSERT(draw.fGeometry.isEmpty());
     SkASSERT(SkIsPow2(fInfo.fShapeTypes));
@@ -363,23 +363,17 @@ bool InstancedRendering::Op::xpRequiresDstTexture(const GrCaps& caps, const GrAp
     }
 
     GrColor overrideColor;
-    if (analysis.initialColorProcessorsToEliminate(&overrideColor)) {
+    if (optimizations.getOverrideColorIfSet(&overrideColor)) {
         SkASSERT(State::kRecordingDraws == fInstancedRendering->fState);
-        this->getSingleDraw().fInstance.fColor = overrideColor;
+        this->getSingleInstance().fColor = overrideColor;
     }
-    fInfo.fCannotTweakAlphaForCoverage =
-            !analysis.isCompatibleWithCoverageAsAlpha() ||
-            !GrXPFactory::CompatibleWithCoverageAsAlpha(fProcessors.xpFactory(),
-                                                        analysis.isOutputColorOpaque());
-
-    fInfo.fUsesLocalCoords = analysis.usesLocalCoords();
-    return GrXPFactory::WillNeedDstTexture(fProcessors.xpFactory(), caps, analysis);
+    fInfo.fUsesLocalCoords = optimizations.readsLocalCoords();
+    fInfo.fCannotTweakAlphaForCoverage = !optimizations.canTweakAlphaForCoverage();
 }
 
 void InstancedRendering::Op::wasRecorded() {
     SkASSERT(!fIsTracked);
     fInstancedRendering->fTrackedOps.addToTail(this);
-    fProcessors.makePendingExecution();
     fIsTracked = true;
 }
 
@@ -389,7 +383,9 @@ bool InstancedRendering::Op::onCombineIfPossible(GrOp* other, const GrCaps& caps
     SkASSERT(fTailDraw);
     SkASSERT(that->fTailDraw);
 
-    if (!OpInfo::CanCombine(fInfo, that->fInfo) || fProcessors != that->fProcessors) {
+    if (!OpInfo::CanCombine(fInfo, that->fInfo) ||
+        !GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
+                                that->bounds(), caps)) {
         return false;
     }
 
@@ -410,9 +406,7 @@ bool InstancedRendering::Op::onCombineIfPossible(GrOp* other, const GrCaps& caps
     this->joinBounds(*that);
     fInfo = combinedInfo;
     fPixelLoad += that->fPixelLoad;
-    fDrawColorsAreOpaque = fDrawColorsAreOpaque && that->fDrawColorsAreOpaque;
-    fDrawColorsAreSame = fDrawColorsAreSame && that->fDrawColorsAreSame &&
-                         fHeadDraw->fInstance.fColor == that->fHeadDraw->fInstance.fColor;
+
     // Adopt the other op's draws.
     fNumDraws += that->fNumDraws;
     fNumChangesInGeometry += that->fNumChangesInGeometry;
@@ -468,40 +462,12 @@ void InstancedRendering::Op::onExecute(GrOpFlushState* state) {
     SkASSERT(state->gpu() == fInstancedRendering->gpu());
 
     state->gpu()->handleDirtyContext();
-
-    GrProcessorSet::FragmentProcessorAnalysis analysis;
-    GrPipelineInput coverageInput;
-    if (GrAAType::kCoverage == fInfo.aaType() ||
-        (GrAAType::kNone == fInfo.aaType() && !fInfo.isSimpleRects() && fInfo.fCannotDiscard)) {
-        coverageInput = GrPipelineInput();
-    } else {
-        coverageInput = GrColor_WHITE;
-    }
-    GrPipelineInput colorInput;
-    if (fDrawColorsAreSame) {
-        colorInput = fHeadDraw->fInstance.fColor;
-    } else if (fDrawColorsAreOpaque) {
-        colorInput = GrPipelineInput::Opaque::kYes;
-    }
-    const GrAppliedClip* clip = state->drawOpArgs().fAppliedClip;
-    analysis.init(colorInput, coverageInput, fProcessors, clip, state->caps());
-
-    GrPipeline pipeline;
-    GrPipeline::InitArgs args;
-    args.fAnalysis = &analysis;
-    args.fAppliedClip = clip;
-    args.fCaps = &state->caps();
-    args.fProcessors = &fProcessors;
-    args.fFlags = GrAATypeIsHW(fInfo.aaType()) ? GrPipeline::kHWAntialias_Flag : 0;
-    args.fRenderTarget = state->drawOpArgs().fRenderTarget;
-    args.fDstTexture = state->drawOpArgs().fDstTexture;
-    pipeline.init(args);
-
-    if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*state->gpu()->caps())) {
-        state->gpu()->xferBarrier(pipeline.getRenderTarget(), barrierType);
+    if (GrXferBarrierType barrierType = this->pipeline()->xferBarrierType(*state->gpu()->caps())) {
+        state->gpu()->xferBarrier(this->pipeline()->getRenderTarget(), barrierType);
     }
+
     InstanceProcessor instProc(fInfo, fInstancedRendering->fParamsBuffer.get());
-    fInstancedRendering->onDraw(pipeline, instProc, this);
+    fInstancedRendering->onDraw(*this->pipeline(), instProc, this);
 }
 
 void InstancedRendering::endFlush() {
index c2db76812169ae25440b94e282d24ba7b6d59412..778e8b4511c569d970c5d869baa2a4e550445f35 100644 (file)
@@ -46,31 +46,35 @@ public:
      * draws between beginFlush() and endFlush().
      */
     std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&,
-                                                               GrPaint&&, GrAA,
-                                                               const GrInstancedPipelineInfo&);
+                                                               GrColor, GrAA,
+                                                               const GrInstancedPipelineInfo&,
+                                                               GrAAType*);
 
     std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&,
-                                                               GrPaint&&, const SkRect& localRect,
-                                                               GrAA,
-                                                               const GrInstancedPipelineInfo&);
+                                                               GrColor, const SkRect& localRect,
+                                                               GrAA, const GrInstancedPipelineInfo&,
+                                                               GrAAType*);
 
     std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&,
-                                                               GrPaint&&,
-                                                               const SkMatrix& localMatrix, GrAA,
-                                                               const GrInstancedPipelineInfo&);
+                                                               GrColor, const SkMatrix& localMatrix,
+                                                               GrAA, const GrInstancedPipelineInfo&,
+                                                               GrAAType*);
 
     std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordOval(const SkRect&, const SkMatrix&,
-                                                               GrPaint&&, GrAA,
-                                                               const GrInstancedPipelineInfo&);
+                                                               GrColor, GrAA,
+                                                               const GrInstancedPipelineInfo&,
+                                                               GrAAType*);
 
     std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRRect(const SkRRect&, const SkMatrix&,
-                                                                GrPaint&&, GrAA,
-                                                                const GrInstancedPipelineInfo&);
+                                                                GrColor, GrAA,
+                                                                const GrInstancedPipelineInfo&,
+                                                                GrAAType*);
 
     std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordDRRect(const SkRRect& outer,
                                                                  const SkRRect& inner,
-                                                                 const SkMatrix&, GrPaint&&, GrAA,
-                                                                 const GrInstancedPipelineInfo&);
+                                                                 const SkMatrix&, GrColor, GrAA,
+                                                                 const GrInstancedPipelineInfo&,
+                                                                 GrAAType*);
 
     /**
      * Compiles all recorded draws into GPU buffers and allows the client to begin flushing the
@@ -118,6 +122,7 @@ protected:
                     fIsTracked,
                     fNumDraws,
                     fNumChangesInGeometry);
+            string.append(DumpPipelineInfo(*this->pipeline()));
             string.append(INHERITED::dumpInfo());
             return string;
         }
@@ -135,32 +140,27 @@ protected:
         void appendParamsTexel(const SkScalar* vals, int count);
         void appendParamsTexel(SkScalar x, SkScalar y, SkScalar z, SkScalar w);
         void appendParamsTexel(SkScalar x, SkScalar y, SkScalar z);
-        FixedFunctionFlags fixedFunctionFlags() const override {
-            return GrAATypeIsHW(fInfo.aaType()) ? FixedFunctionFlags::kUsesHWAA
-                                                : FixedFunctionFlags::kNone;
-        }
-        bool xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*) override;
 
         // Registers the op with the InstancedRendering list of tracked ops.
         void wasRecorded() override;
 
     protected:
-        Op(uint32_t classID, GrPaint&&, InstancedRendering*);
+        Op(uint32_t classID, InstancedRendering* ir);
 
         InstancedRendering* const fInstancedRendering;
         OpInfo fInfo;
         SkScalar fPixelLoad;
-        GrProcessorSet fProcessors;
         SkSTArray<5, ParamsTexel, true> fParams;
-        bool fIsTracked : 1;
-        bool fDrawColorsAreOpaque : 1;
-        bool fDrawColorsAreSame : 1;
+        bool fIsTracked;
         int fNumDraws;
         int fNumChangesInGeometry;
         Draw* fHeadDraw;
         Draw* fTailDraw;
 
     private:
+        void getFragmentProcessorAnalysisInputs(
+                FragmentProcessorAnalysisInputs* input) const override;
+        void applyPipelineOptimizations(const GrPipelineOptimizations&) override;
         bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override;
         void onPrepare(GrOpFlushState*) override {}
         void onExecute(GrOpFlushState*) override;
@@ -190,14 +190,15 @@ private:
     };
 
     std::unique_ptr<Op> SK_WARN_UNUSED_RESULT recordShape(ShapeType, const SkRect& bounds,
-                                                          const SkMatrix& viewMatrix, GrPaint&&,
+                                                          const SkMatrix& viewMatrix, GrColor,
                                                           const SkRect& localRect, GrAA aa,
-                                                          const GrInstancedPipelineInfo&);
+                                                          const GrInstancedPipelineInfo&,
+                                                          GrAAType*);
 
     bool selectAntialiasMode(const SkMatrix& viewMatrix, GrAA aa, const GrInstancedPipelineInfo&,
                              GrAAType*);
 
-    virtual std::unique_ptr<Op> makeOp(GrPaint&&) = 0;
+    virtual std::unique_ptr<Op> makeOp() = 0;
 
     const sk_sp<GrGpu> fGpu;
     State fState;
index 0458370bcdce42054a93babd73b4e4ba965585ea..62a16887ee284d94a895f7b06ae2de69d2c99e2c 100644 (file)
@@ -12,8 +12,6 @@
 #include "GrOp.h"
 #include "GrPipeline.h"
 
-class GrAppliedClip;
-
 /**
  * GrDrawOps are flushed in two phases (preDraw, and draw). In preDraw uploads to GrGpuResources
  * and draws are determined and scheduled. They are issued in the draw phase. GrDrawOpUploadToken is
@@ -58,27 +56,22 @@ public:
 
     GrDrawOp(uint32_t classID) : INHERITED(classID) {}
 
-    /**
-     * This information is required to determine how to compute a GrAppliedClip from a GrClip for
-     * this op.
-     */
-    enum class FixedFunctionFlags : uint32_t {
-        kNone = 0x0,
-        /** Indices that the op will enable MSAA or mixed samples rendering. */
-        kUsesHWAA = 0x1,
-        /** Indices that the op reads and/or writes the stencil buffer */
-        kUsesStencil = 0x2,
-    };
-    GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(FixedFunctionFlags);
-    virtual FixedFunctionFlags fixedFunctionFlags() const = 0;
+    void initPipeline(const GrPipeline::InitArgs& args) {
+        this->applyPipelineOptimizations(fPipeline.init(args));
+    }
 
     /**
-     * This is called after the GrAppliedClip has been computed and just prior to recording the op
-     * or combining it with a previously recorded op. It is used to determine whether a copy of the
-     * destination (or destination texture itself) needs to be provided to the xp when this op
-     * executes.
+     * Performs analysis of the fragment processors in GrProcessorSet and GrAppliedClip using the
+     * initial color and coverage from this op's geometry processor.
      */
-    virtual bool xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*) = 0;
+    void analyzeProcessors(GrProcessorSet::FragmentProcessorAnalysis* analysis,
+                           const GrProcessorSet& processors,
+                           const GrAppliedClip* appliedClip,
+                           const GrCaps& caps) const {
+        FragmentProcessorAnalysisInputs input;
+        this->getFragmentProcessorAnalysisInputs(&input);
+        analysis->init(*input.colorInput(), *input.coverageInput(), processors, appliedClip, caps);
+    }
 
 protected:
     static SkString DumpPipelineInfo(const GrPipeline& pipeline) {
@@ -112,20 +105,53 @@ protected:
         return string;
     }
 
+    const GrPipeline* pipeline() const {
+        SkASSERT(fPipeline.isInitialized());
+        return &fPipeline;
+    }
+
+    /**
+     * This describes aspects of the GrPrimitiveProcessor produced by a GrDrawOp that are used in
+     * pipeline analysis.
+     */
+    class FragmentProcessorAnalysisInputs {
+    public:
+        FragmentProcessorAnalysisInputs() = default;
+        GrPipelineInput* colorInput() { return &fColorInput; }
+        GrPipelineInput* coverageInput() { return &fCoverageInput; }
+
+    private:
+        GrPipelineInput fColorInput;
+        GrPipelineInput fCoverageInput;
+    };
+
+private:
+    /**
+     * Provides information about the GrPrimitiveProccesor color and coverage outputs which become
+     * inputs to the first color and coverage fragment processors.
+     */
+    virtual void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs*) const = 0;
+
+    /**
+     * After GrPipeline analysis is complete this is called so that the op can use the analysis
+     * results when constructing its GrPrimitiveProcessor.
+     */
+    virtual void applyPipelineOptimizations(const GrPipelineOptimizations&) = 0;
+
+protected:
     struct QueuedUpload {
         QueuedUpload(DeferredUploadFn&& upload, GrDrawOpUploadToken token)
             : fUpload(std::move(upload))
             , fUploadBeforeToken(token) {}
-        DeferredUploadFn fUpload;
+        DeferredUploadFn    fUpload;
         GrDrawOpUploadToken fUploadBeforeToken;
     };
 
-    SkTArray<QueuedUpload> fInlineUploads;
+    SkTArray<QueuedUpload>                          fInlineUploads;
 
 private:
+    GrPipeline fPipeline;
     typedef GrOp INHERITED;
 };
 
-GR_MAKE_BITFIELD_CLASS_OPS(GrDrawOp::FixedFunctionFlags);
-
 #endif
index fa08ae6d547c003854c63bf91abce5e8d739fe40..85fb1473d52246d212abce1fa10f99699f0395aa 100644 (file)
@@ -6,78 +6,36 @@
  */
 
 #include "GrDrawPathOp.h"
-#include "GrAppliedClip.h"
-#include "GrRenderTargetContext.h"
+
 #include "GrRenderTargetPriv.h"
-#include "SkTemplates.h"
 
-GrDrawPathOpBase::GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&& paint,
-                                   GrPathRendering::FillType fill, GrAA aa)
-        : INHERITED(classID)
-        , fViewMatrix(viewMatrix)
-        , fProcessorSet(std::move(paint))
-        , fAnalysis(paint.getColor())
-        , fFillType(fill)
-        , fAA(aa) {}
+static void pre_translate_transform_values(const float* xforms,
+                                           GrPathRendering::PathTransformType type, int count,
+                                           SkScalar x, SkScalar y, float* dst);
+
+void GrDrawPathOpBase::onPrepare(GrOpFlushState*) {
+    const GrRenderTargetPriv& rtPriv = this->pipeline()->getRenderTarget()->renderTargetPriv();
+    fStencilPassSettings.reset(GrPathRendering::GetStencilPassSettings(fFillType),
+                               this->pipeline()->hasStencilClip(), rtPriv.numStencilBits());
+}
 
 SkString GrDrawPathOp::dumpInfo() const {
     SkString string;
     string.printf("PATH: 0x%p", fPath.get());
+    string.append(DumpPipelineInfo(*this->pipeline()));
     string.append(INHERITED::dumpInfo());
     return string;
 }
 
-GrPipelineOptimizations GrDrawPathOpBase::initPipeline(const GrOpFlushState& state,
-                                                       GrPipeline* pipeline) {
-    static constexpr GrUserStencilSettings kCoverPass{
-            GrUserStencilSettings::StaticInit<
-                    0x0000,
-                    GrUserStencilTest::kNotEqual,
-                    0xffff,
-                    GrUserStencilOp::kZero,
-                    GrUserStencilOp::kKeep,
-                    0xffff>()
-    };
-    GrPipeline::InitArgs args;
-    args.fProcessors = &this->processors();
-    args.fFlags = GrAA::kYes == fAA ? GrPipeline::kHWAntialias_Flag : 0;
-    args.fUserStencil = &kCoverPass;
-    args.fAppliedClip = state.drawOpArgs().fAppliedClip;
-    args.fRenderTarget = state.drawOpArgs().fRenderTarget;
-    args.fCaps = &state.caps();
-    args.fDstTexture = state.drawOpArgs().fDstTexture;
-    args.fAnalysis =
-            &this->doFragmentProcessorAnalysis(state.caps(), state.drawOpArgs().fAppliedClip);
-
-    return pipeline->init(args);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void init_stencil_pass_settings(const GrOpFlushState& flushState,
-                                GrPathRendering::FillType fillType, GrStencilSettings* stencil) {
-    const GrAppliedClip* appliedClip = flushState.drawOpArgs().fAppliedClip;
-    bool stencilClip = appliedClip && appliedClip->hasStencilClip();
-    stencil->reset(GrPathRendering::GetStencilPassSettings(fillType), stencilClip,
-                   flushState.drawOpArgs().fRenderTarget->renderTargetPriv().numStencilBits());
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
 void GrDrawPathOp::onExecute(GrOpFlushState* state) {
-    GrColor color = this->color();
-    GrPipeline pipeline;
-    GrPipelineOptimizations optimizations = this->initPipeline(*state, &pipeline);
-    optimizations.getOverrideColorIfSet(&color);
-    sk_sp<GrPathProcessor> pathProc(GrPathProcessor::Create(color, this->viewMatrix()));
+    GrProgramDesc desc;
 
-    GrStencilSettings stencil;
-    init_stencil_pass_settings(*state, this->fillType(), &stencil);
-    state->gpu()->pathRendering()->drawPath(pipeline, *pathProc, stencil, fPath.get());
+    sk_sp<GrPathProcessor> pathProc(
+            GrPathProcessor::Create(this->color(), this->viewMatrix()));
+    state->gpu()->pathRendering()->drawPath(*this->pipeline(), *pathProc,
+                                            this->stencilPassSettings(), fPath.get());
 }
 
-//////////////////////////////////////////////////////////////////////////////
-
 SkString GrDrawPathRangeOp::dumpInfo() const {
     SkString string;
     string.printf("RANGE: 0x%p COUNTS: [", fPathRange.get());
@@ -86,15 +44,16 @@ SkString GrDrawPathRangeOp::dumpInfo() const {
     }
     string.remove(string.size() - 2, 2);
     string.append("]");
+    string.append(DumpPipelineInfo(*this->pipeline()));
     string.append(INHERITED::dumpInfo());
     return string;
 }
 
 GrDrawPathRangeOp::GrDrawPathRangeOp(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x,
-                                     SkScalar y, GrPaint&& paint, GrPathRendering::FillType fill,
-                                     GrAA aa, GrPathRange* range, const InstanceData* instanceData,
+                                     SkScalar y, GrColor color, GrPathRendering::FillType fill,
+                                     GrPathRange* range, const InstanceData* instanceData,
                                      const SkRect& bounds)
-        : INHERITED(ClassID(), viewMatrix, std::move(paint), fill, aa)
+        : INHERITED(ClassID(), viewMatrix, color, fill)
         , fPathRange(range)
         , fTotalPathCount(instanceData->count())
         , fScale(scale) {
@@ -102,10 +61,6 @@ GrDrawPathRangeOp::GrDrawPathRangeOp(const SkMatrix& viewMatrix, SkScalar scale,
     this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
 }
 
-static void pre_translate_transform_values(const float* xforms,
-                                           GrPathRendering::PathTransformType type, int count,
-                                           SkScalar x, SkScalar y, float* dst);
-
 bool GrDrawPathRangeOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
     GrDrawPathRangeOp* that = t->cast<GrDrawPathRangeOp>();
     if (this->fPathRange.get() != that->fPathRange.get() ||
@@ -113,7 +68,7 @@ bool GrDrawPathRangeOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
         this->color() != that->color() || !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
         return false;
     }
-    if (this->processors() != that->processors()) {
+    if (!GrPipeline::AreEqual(*this->pipeline(), *that->pipeline())) {
         return false;
     }
     switch (fDraws.head()->fInstanceData->transformType()) {
@@ -143,20 +98,11 @@ bool GrDrawPathRangeOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
     // work). Note that it's also possible for overlapping paths to cancel each other's winding
     // numbers, and we only partially account for this by not allowing even/odd paths to be
     // combined. (Glyphs in the same font tend to wind the same direction so it works out OK.)
-
     if (GrPathRendering::kWinding_FillType != this->fillType() ||
-        GrPathRendering::kWinding_FillType != that->fillType()) {
-        return false;
-    }
-    // If we have non-clipping coverage processors we don't try to merge as its unclear whether it
-    // will be correct. We don't expect this to happen in practice.
-    if (this->processors().numCoverageFragmentProcessors()) {
-        return false;
-    }
-    bool opaque = this->fragmentProcessorAnalysis().isOutputColorOpaque();
-    if (!GrXPFactory::CanCombineOverlappedStencilAndCover(this->processors().xpFactory(), opaque)) {
+        GrPathRendering::kWinding_FillType != that->fillType() || this->xpReadsDst()) {
         return false;
     }
+    SkASSERT(!that->xpReadsDst());
     fTotalPathCount += that->fTotalPathCount;
     while (Draw* head = that->fDraws.head()) {
         Draw* draw = fDraws.addToTail();
@@ -183,15 +129,11 @@ void GrDrawPathRangeOp::onExecute(GrOpFlushState* state) {
     sk_sp<GrPathProcessor> pathProc(
             GrPathProcessor::Create(this->color(), drawMatrix, localMatrix));
 
-    GrPipeline pipeline;
-    this->initPipeline(*state, &pipeline);
-    GrStencilSettings stencil;
-    init_stencil_pass_settings(*state, this->fillType(), &stencil);
     if (fDraws.count() == 1) {
         const InstanceData& instances = *head.fInstanceData;
-        state->gpu()->pathRendering()->drawPaths(pipeline,
+        state->gpu()->pathRendering()->drawPaths(*this->pipeline(),
                                                  *pathProc,
-                                                 stencil,
+                                                 this->stencilPassSettings(),
                                                  fPathRange.get(),
                                                  instances.indices(),
                                                  GrPathRange::kU16_PathIndexType,
@@ -217,9 +159,9 @@ void GrDrawPathRangeOp::onExecute(GrOpFlushState* state) {
         }
         SkASSERT(idx == fTotalPathCount);
 
-        state->gpu()->pathRendering()->drawPaths(pipeline,
+        state->gpu()->pathRendering()->drawPaths(*this->pipeline(),
                                                  *pathProc,
-                                                 stencil,
+                                                 this->stencilPassSettings(),
                                                  fPathRange.get(),
                                                  indexStorage,
                                                  GrPathRange::kU16_PathIndexType,
index cf3ce2f11ce605ce3dbddea67b18d97978b97dba..ffe8768cc040e1be59833aae35fbf81d26601522 100644 (file)
 #include "GrPath.h"
 #include "GrPathProcessor.h"
 #include "GrPathRendering.h"
-#include "GrProcessorSet.h"
 #include "GrStencilSettings.h"
 
 #include "SkTLList.h"
 
-class GrPaint;
-
 class GrDrawPathOpBase : public GrDrawOp {
 protected:
-    GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&& paint,
-                     GrPathRendering::FillType fill, GrAA aa);
-    FixedFunctionFlags fixedFunctionFlags() const override {
-        return FixedFunctionFlags::kUsesHWAA | FixedFunctionFlags::kUsesStencil;
-    }
-    bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) override {
-        return GrXPFactory::WillNeedDstTexture(fProcessorSet.xpFactory(), caps,
-                                               this->doFragmentProcessorAnalysis(caps, clip));
-    }
+    GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrColor initialColor,
+                     GrPathRendering::FillType fill)
+            : INHERITED(classID), fViewMatrix(viewMatrix), fColor(initialColor), fFillType(fill) {}
 
-    void wasRecorded() override { fProcessorSet.makePendingExecution(); }
+    const GrStencilSettings& stencilPassSettings() const {
+        SkASSERT(!fStencilPassSettings.isDisabled());  // This shouldn't be called before onPrepare.
+        return fStencilPassSettings;
+    }
 
 protected:
     const SkMatrix& viewMatrix() const { return fViewMatrix; }
-    GrColor color() const { return fAnalysis.inputColor(); }
+    GrColor color() const { return fColor; }
     GrPathRendering::FillType fillType() const { return fFillType; }
-    const GrProcessorSet& processors() const { return fProcessorSet; }
-    GrPipelineOptimizations initPipeline(const GrOpFlushState&, GrPipeline*);
-    const GrProcessorSet::FragmentProcessorAnalysis& doFragmentProcessorAnalysis(
-            const GrCaps& caps, const GrAppliedClip* clip) {
-        if (!fAnalysis.isInitializedWithProcessorSet()) {
-            fAnalysis.init(fAnalysis.inputColor(), GrColor_WHITE, fProcessorSet, clip, caps);
-        }
-        return fAnalysis;
+    bool xpReadsDst() const { return fXPReadsDst; }
+
+private:
+    void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
+        input->colorInput()->setToConstant(fColor);
+        input->coverageInput()->setToSolidCoverage();
     }
-    const GrProcessorSet::FragmentProcessorAnalysis& fragmentProcessorAnalysis() const {
-        SkASSERT(fAnalysis.isInitializedWithProcessorSet());
-        return fAnalysis;
+
+    void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {
+        optimizations.getOverrideColorIfSet(&fColor);
+        fXPReadsDst = optimizations.xpReadsDst();
     }
 
-private:
-    void onPrepare(GrOpFlushState*) final {}
+    void onPrepare(GrOpFlushState*) override;  // Initializes fStencilPassSettings.
 
     SkMatrix fViewMatrix;
-    GrProcessorSet fProcessorSet;
-    GrProcessorSet::FragmentProcessorAnalysis fAnalysis;
+    GrColor fColor;
     GrPathRendering::FillType fFillType;
-    GrAA fAA;
+    GrStencilSettings fStencilPassSettings;
+    bool fXPReadsDst;
 
     typedef GrDrawOp INHERITED;
 };
@@ -69,9 +61,9 @@ class GrDrawPathOp final : public GrDrawPathOpBase {
 public:
     DEFINE_OP_CLASS_ID
 
-    static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, GrPaint&& paint, GrAA aa,
-                                          GrPath* path) {
-        return std::unique_ptr<GrDrawOp>(new GrDrawPathOp(viewMatrix, std::move(paint), aa, path));
+    static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, GrColor color,
+                                          const GrPath* path) {
+        return std::unique_ptr<GrDrawOp>(new GrDrawPathOp(viewMatrix, color, path));
     }
 
     const char* name() const override { return "DrawPath"; }
@@ -79,9 +71,8 @@ public:
     SkString dumpInfo() const override;
 
 private:
-    GrDrawPathOp(const SkMatrix& viewMatrix, GrPaint&& paint, GrAA aa, const GrPath* path)
-            : GrDrawPathOpBase(ClassID(), viewMatrix, std::move(paint), path->getFillType(), aa)
-            , fPath(path) {
+    GrDrawPathOp(const SkMatrix& viewMatrix, GrColor color, const GrPath* path)
+            : GrDrawPathOpBase(ClassID(), viewMatrix, color, path->getFillType()), fPath(path) {
         this->setTransformedBounds(path->getBounds(), viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
     }
 
@@ -161,12 +152,11 @@ public:
     };
 
     static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x,
-                                          SkScalar y, GrPaint&& paint,
-                                          GrPathRendering::FillType fill, GrAA aa,
+                                          SkScalar y, GrColor color, GrPathRendering::FillType fill,
                                           GrPathRange* range, const InstanceData* instanceData,
                                           const SkRect& bounds) {
-        return std::unique_ptr<GrDrawOp>(new GrDrawPathRangeOp(
-                viewMatrix, scale, x, y, std::move(paint), fill, aa, range, instanceData, bounds));
+        return std::unique_ptr<GrDrawOp>(new GrDrawPathRangeOp(viewMatrix, scale, x, y, color, fill,
+                                                               range, instanceData, bounds));
     }
 
     const char* name() const override { return "DrawPathRange"; }
@@ -175,7 +165,7 @@ public:
 
 private:
     GrDrawPathRangeOp(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x, SkScalar y,
-                      GrPaint&& paint, GrPathRendering::FillType fill, GrAA aa, GrPathRange* range,
+                      GrColor color, GrPathRendering::FillType fill, GrPathRange* range,
                       const InstanceData* instanceData, const SkRect& bounds);
 
     TransformType transformType() const { return fDraws.head()->fInstanceData->transformType(); }
index 59335d41dbc23c9672b76be4555614f66dac51be..5d83bd536451496678a15e1756936312298d0de5 100644 (file)
@@ -60,9 +60,6 @@ void* GrMeshDrawOp::QuadHelper::init(Target* target, size_t vertexStride, int qu
 }
 
 void GrMeshDrawOp::onExecute(GrOpFlushState* state) {
-    SkASSERT(!state->drawOpArgs().fAppliedClip);
-    SkASSERT(!state->drawOpArgs().fDstTexture.texture());
-    SkASSERT(state->drawOpArgs().fRenderTarget == this->pipeline()->getRenderTarget());
     int currUploadIdx = 0;
     int currMeshIdx = 0;
 
index 4cf7c52672a64a3490306e29291900dc24e5de9a..a7d312f151674030ba3cbd0771d9b81911d762f6 100644 (file)
@@ -15,7 +15,6 @@
 
 #include "SkTLList.h"
 
-class GrCaps;
 class GrOpFlushState;
 
 /**
@@ -25,39 +24,9 @@ class GrMeshDrawOp : public GrDrawOp {
 public:
     class Target;
 
-    /**
-     * Performs analysis of the fragment processors in GrProcessorSet and GrAppliedClip using the
-     * initial color and coverage from this op's geometry processor.
-     */
-    void analyzeProcessors(GrProcessorSet::FragmentProcessorAnalysis* analysis,
-                           const GrProcessorSet& processors,
-                           const GrAppliedClip* appliedClip,
-                           const GrCaps& caps) const {
-        FragmentProcessorAnalysisInputs input;
-        this->getFragmentProcessorAnalysisInputs(&input);
-        analysis->init(*input.colorInput(), *input.coverageInput(), processors, appliedClip, caps);
-    }
-
-    void initPipeline(const GrPipeline::InitArgs& args) {
-        this->applyPipelineOptimizations(fPipeline.init(args));
-    }
-
-    /**
-     * Mesh draw ops use a legacy system in GrRenderTargetContext where the pipeline is created when
-     * the op is recorded. These methods are unnecessary as this information is in the pipeline.
-     */
-    FixedFunctionFlags fixedFunctionFlags() const override {
-        SkFAIL("This should never be called for mesh draw ops.");
-        return FixedFunctionFlags::kNone;
-    }
-    bool xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*) override {
-        SkFAIL("Should never be called for mesh draw ops.");
-        return false;
-    }
-
-protected:
     GrMeshDrawOp(uint32_t classID);
 
+protected:
     /** Helper for rendering instances using an instanced index index buffer. This class creates the
         space for the vertices and flushes the draws to the GrMeshDrawOp::Target. */
     class InstancedHelper {
@@ -93,39 +62,7 @@ protected:
         typedef InstancedHelper INHERITED;
     };
 
-    const GrPipeline* pipeline() const {
-        SkASSERT(fPipeline.isInitialized());
-        return &fPipeline;
-    }
-
-    /**
-     * This describes aspects of the GrPrimitiveProcessor produced by a GrDrawOp that are used in
-     * pipeline analysis.
-     */
-    class FragmentProcessorAnalysisInputs {
-    public:
-        FragmentProcessorAnalysisInputs() = default;
-        GrPipelineInput* colorInput() { return &fColorInput; }
-        GrPipelineInput* coverageInput() { return &fCoverageInput; }
-
-    private:
-        GrPipelineInput fColorInput;
-        GrPipelineInput fCoverageInput;
-    };
-
 private:
-    /**
-     * Provides information about the GrPrimitiveProccesor color and coverage outputs which become
-     * inputs to the first color and coverage fragment processors.
-     */
-    virtual void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs*) const = 0;
-
-    /**
-     * After GrPipeline analysis is complete this is called so that the op can use the analysis
-     * results when constructing its GrPrimitiveProcessor.
-     */
-    virtual void applyPipelineOptimizations(const GrPipelineOptimizations&) = 0;
-
     void onPrepare(GrOpFlushState* state) final;
     void onExecute(GrOpFlushState* state) final;
 
@@ -145,7 +82,7 @@ private:
     // globally across all ops. This is the offset of the first entry in fQueuedDraws.
     // fQueuedDraws[i]'s token is fBaseDrawToken + i.
     GrDrawOpUploadToken fBaseDrawToken;
-    GrPipeline fPipeline;
+
     SkSTArray<4, GrMesh> fMeshes;
     SkSTArray<4, QueuedDraw, true> fQueuedDraws;
 
index ef752b5d0c29736bbab0493bb7b7a6c20c7d9508..c1bf7f755541735b88b1964f2389fd813e986542 100644 (file)
@@ -11,7 +11,6 @@
 #include "../private/SkAtomics.h"
 #include "GrGpuResource.h"
 #include "GrNonAtomicRef.h"
-#include "GrXferProcessor.h"
 #include "SkMatrix.h"
 #include "SkRect.h"
 #include "SkString.h"
index 4c2edf408f307c8004c351c0c0372c74d85f77c5..3b3816329d4e4e8c72343b4afa79843c3231f179 100644 (file)
@@ -145,10 +145,22 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) {
                                                      std::move(coverOp));
         }
     } else {
-        GrAA aa = GrBoolToAA(GrAATypeIsHW(args.fAAType));
+        static constexpr GrUserStencilSettings kCoverPass(
+            GrUserStencilSettings::StaticInit<
+                0x0000,
+                GrUserStencilTest::kNotEqual,
+                0xffff,
+                GrUserStencilOp::kZero,
+                GrUserStencilOp::kKeep,
+                0xffff>()
+        );
+
         std::unique_ptr<GrDrawOp> op =
-                GrDrawPathOp::Make(viewMatrix, std::move(args.fPaint), aa, path.get());
-        args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+                GrDrawPathOp::Make(viewMatrix, args.fPaint.getColor(), path.get());
+
+        GrPipelineBuilder pipelineBuilder(std::move(args.fPaint), args.fAAType);
+        pipelineBuilder.setUserStencil(&kCoverPass);
+        args.fRenderTargetContext->addDrawOp(pipelineBuilder, *args.fClip, std::move(op));
     }
 
     return true;
index e572e5d633df310277bbfc6c1802687aa41c1f4e..acd426787bd4c22cca98ceb609d0344cd80ce923 100644 (file)
@@ -605,13 +605,24 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx,
         const SkRect bounds = SkRect::MakeIWH(renderTargetContext->width(),
                                               renderTargetContext->height());
 
-        // The run's "font" overrides the anti-aliasing of the passed in SkPaint!
         std::unique_ptr<GrDrawOp> op = GrDrawPathRangeOp::Make(
                 viewMatrix, fTextRatio, fTextInverseRatio * x, fTextInverseRatio * y,
-                std::move(grPaint), GrPathRendering::kWinding_FillType, runAA, glyphs.get(),
+                grPaint.getColor(), GrPathRendering::kWinding_FillType, glyphs.get(),
                 fInstanceData.get(), bounds);
 
-        renderTargetContext->addDrawOp(clip, std::move(op));
+        // The run's "font" overrides the anti-aliasing of the passed in SkPaint!
+        GrAAType aaType = GrAAType::kNone;
+        if (GrAA::kYes == runAA) {
+            if (renderTargetContext->isUnifiedMultisampled()) {
+                aaType = GrAAType::kMSAA;
+            } else if (renderTargetContext->isStencilBufferMultisampled()) {
+                aaType = GrAAType::kMixedSamples;
+            }
+        }
+        GrPipelineBuilder pipelineBuilder(std::move(grPaint), aaType);
+        pipelineBuilder.setUserStencil(&kCoverPass);
+
+        renderTargetContext->addDrawOp(pipelineBuilder, clip, std::move(op));
     }
 
     if (fFallbackTextBlob) {
index 5cb9b606db7a595df6f89357ab20ac83b8a79b5c..8808b1d8cbfeaf47c33a0b62b538847c0fcff828 100644 (file)
@@ -96,12 +96,14 @@ static void construct_dummy_pipeline(GrRenderTargetContext* dc, GrPipeline* pipe
     GrScissorState dummyScissor;
     GrWindowRectsState dummyWindows;
 
+    GrAppliedClip dummyAppliedClip;
     GrProcessorSet::FragmentProcessorAnalysis analysis;
     GrPipeline::InitArgs args;
     dummyBuilder.getPipelineInitArgs(&args);
     args.fRenderTarget = dc->accessRenderTarget();
     args.fAnalysis = &analysis;
     args.fCaps = dc->caps();
+    args.fAppliedClip = &dummyAppliedClip;
     args.fDstTexture = GrXferProcessor::DstTexture();
     pipeline->init(args);
 }
index de1843813af682ae28f864e17f83d714a5e14251..ddca03a497ecd74930dd5f11a9e12eb118e95877 100644 (file)
@@ -9,6 +9,7 @@
 
 #if SK_SUPPORT_GPU
 
+#include "GrAppliedClip.h"
 #include "GrContextFactory.h"
 #include "GrContextOptions.h"
 #include "GrGpu.h"
@@ -67,10 +68,7 @@ public:
         XPInfo(skiatest::Reporter* reporter, SkBlendMode xfermode, const GrCaps& caps,
                const GrProcessorSet::FragmentProcessorAnalysis& analysis) {
             const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(xfermode);
-            // The GrXPFactory query assumes no coverage.
-            fCanCombineOverlappedStencilAndCover =
-                    !analysis.hasCoverage() && GrXPFactory::CanCombineOverlappedStencilAndCover(
-                                                       xpf, analysis.isOutputColorOpaque());
+            fReadsDst = GrXPFactory::WillReadDst(xpf, analysis);
             sk_sp<GrXferProcessor> xp(xpf->createXferProcessor(analysis, false, nullptr, caps));
             TEST_ASSERT(!GrXPFactory::WillNeedDstTexture(xpf, caps, analysis));
             fOptFlags = xp->getOptimizations(analysis);
@@ -80,7 +78,7 @@ public:
             TEST_ASSERT(xp->hasSecondaryOutput() == GrBlendCoeffRefsSrc2(fBlendInfo.fDstBlend));
         }
 
-        bool fCanCombineOverlappedStencilAndCover;
+        bool fReadsDst;
         int fOptFlags;
         int fPrimaryOutputType;
         int fSecondaryOutputType;
@@ -106,7 +104,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
         const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, analysis);
         switch (xfermode) {
             case SkBlendMode::kClear:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -116,7 +114,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrc:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType);
@@ -126,7 +124,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDst:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kIgnoreColor_OptFlag |
                              kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
@@ -137,7 +135,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(!xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcOver:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kSAModulate_OutputType == xpi.fSecondaryOutputType);
@@ -147,7 +145,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstOver:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -157,7 +155,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcIn:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType);
@@ -167,7 +165,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstIn:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kISAModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -177,7 +175,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcOut:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType);
@@ -187,7 +185,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstOut:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kSAModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -197,7 +195,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcATop:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kSAModulate_OutputType == xpi.fSecondaryOutputType);
@@ -207,7 +205,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstATop:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kISAModulate_OutputType == xpi.fSecondaryOutputType);
@@ -217,7 +215,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kXor:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kSAModulate_OutputType == xpi.fSecondaryOutputType);
@@ -227,7 +225,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kPlus:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -237,7 +235,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kModulate:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kISCModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -247,7 +245,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kScreen:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -275,7 +273,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
         const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, analysis);
         switch (xfermode) {
             case SkBlendMode::kClear:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -285,7 +283,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrc:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType);
@@ -295,7 +293,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDst:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kIgnoreColor_OptFlag |
                              kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
@@ -306,7 +304,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(!xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcOver:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -316,7 +314,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstOver:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -326,7 +324,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcIn:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType);
@@ -336,7 +334,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstIn:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kISAModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -346,7 +344,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcOut:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType);
@@ -356,7 +354,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstOut:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -366,7 +364,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcATop:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -376,7 +374,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstATop:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kISAModulate_OutputType == xpi.fSecondaryOutputType);
@@ -386,7 +384,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kXor:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -396,7 +394,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kPlus:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -406,7 +404,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kModulate:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kISCModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -416,7 +414,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kScreen:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -445,7 +443,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
         const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, analysis);
         switch (xfermode) {
             case SkBlendMode::kClear:
-                TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(!xpi.fReadsDst);
                 TEST_ASSERT(kIgnoreColor_OptFlag == xpi.fOptFlags);
                 TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -455,7 +453,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrc:
-                TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(!xpi.fReadsDst);
                 TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -465,7 +463,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDst:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kIgnoreColor_OptFlag |
                              kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
@@ -476,7 +474,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(!xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcOver:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -486,7 +484,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstOver:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -496,7 +494,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcIn:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -506,7 +504,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstIn:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -516,7 +514,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcOut:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -526,7 +524,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstOut:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -536,7 +534,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcATop:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -546,7 +544,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstATop:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -556,7 +554,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kXor:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -566,7 +564,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kPlus:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -576,7 +574,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kModulate:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -586,7 +584,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kScreen:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -616,7 +614,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
         const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, analysis);
         switch (xfermode) {
             case SkBlendMode::kClear:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -626,7 +624,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrc:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -636,7 +634,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDst:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kIgnoreColor_OptFlag |
                              kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
@@ -647,7 +645,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(!xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcOver:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -657,7 +655,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstOver:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -667,7 +665,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcIn:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -677,7 +675,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstIn:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kIgnoreColor_OptFlag |
                              kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
@@ -688,7 +686,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(!xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcOut:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -698,7 +696,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstOut:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -708,7 +706,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcATop:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -718,7 +716,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstATop:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -728,7 +726,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kXor:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -738,7 +736,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kPlus:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -748,7 +746,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kModulate:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
                 TEST_ASSERT(kISCModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -758,7 +756,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kScreen:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -788,7 +786,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
 
         switch (xfermode) {
             case SkBlendMode::kClear:
-                TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(!xpi.fReadsDst);
                 TEST_ASSERT(kIgnoreColor_OptFlag == xpi.fOptFlags);
                 TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -798,7 +796,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrc:
-                TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(!xpi.fReadsDst);
                 TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -808,7 +806,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDst:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kIgnoreColor_OptFlag |
                              kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
@@ -819,7 +817,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(!xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcOver:
-                TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(!xpi.fReadsDst);
                 TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -829,7 +827,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstOver:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -839,7 +837,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcIn:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -849,7 +847,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstIn:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT((kIgnoreColor_OptFlag |
                              kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
                 TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
@@ -860,7 +858,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(!xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcOut:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -870,7 +868,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstOut:
-                TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(!xpi.fReadsDst);
                 TEST_ASSERT(kIgnoreColor_OptFlag == xpi.fOptFlags);
                 TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -880,7 +878,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kSrcATop:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -890,7 +888,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kDstATop:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -900,7 +898,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kXor:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -910,7 +908,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kPlus:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -920,7 +918,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kModulate:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -930,7 +928,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
                 TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
                 break;
             case SkBlendMode::kScreen:
-                TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
+                TEST_ASSERT(xpi.fReadsDst);
                 TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
                 TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
                 TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
@@ -963,14 +961,15 @@ static void test_lcd_coverage_fallback_case(skiatest::Reporter* reporter, const
         }
 
         void applyPipelineOptimizations(const GrPipelineOptimizations&) override {}
-        bool onCombineIfPossible(GrOp*, const GrCaps&) override { return false; }
+        bool onCombineIfPossible(GrOp*, const GrCaps&) override  { return false; }
         void onPrepareDraws(Target*) const override {}
 
         typedef GrMeshDrawOp INHERITED;
     } testLCDCoverageOp;
 
     GrProcessorSet::FragmentProcessorAnalysis analysis;
-    testLCDCoverageOp.analyzeProcessors(&analysis, GrProcessorSet(GrPaint()), nullptr, caps);
+    GrAppliedClip clip;
+    testLCDCoverageOp.analyzeProcessors(&analysis, GrProcessorSet(GrPaint()), &clip, caps);
 
     SkASSERT(analysis.hasKnownOutputColor());
     SkASSERT(analysis.hasLCDCoverage());
@@ -984,6 +983,8 @@ static void test_lcd_coverage_fallback_case(skiatest::Reporter* reporter, const
         return;
     }
 
+    TEST_ASSERT(GrXPFactory::WillReadDst(xpf, analysis));
+
     xp->getOptimizations(analysis);
 
     GrXferProcessor::BlendInfo blendInfo;