diff options
author | Brian Salomon <bsalomon@google.com> | 2017-03-21 14:22:38 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-03-21 23:55:32 +0000 |
commit | 54d212e1bfaea0be88c3c40820d0b1ae0daebecf (patch) | |
tree | ce606e9d88dfd04d592d406881b7e6e5d9a855cf | |
parent | 337432dc092619431eaa62f13e6347f2272f1fa7 (diff) |
Revert "Revert "Remove GrPipeline from GrDrawOp.""
This reverts commit c48af934608bbb65650641f66adb51f2102d4274.
Change-Id: I4ba78fd7e5a7d406b88223ca6f7245c029b60f76
Reviewed-on: https://skia-review.googlesource.com/9981
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
34 files changed, 764 insertions, 481 deletions
diff --git a/include/gpu/GrProgramElement.h b/include/gpu/GrProgramElement.h index 0e065c231f..2538680302 100644 --- a/include/gpu/GrProgramElement.h +++ b/include/gpu/GrProgramElement.h @@ -84,7 +84,6 @@ protected: void addPendingExecution() const { this->validate(); - SkASSERT(fRefCnt > 0); if (0 == fPendingExecutions) { static_cast<const DERIVED*>(this)->addPendingIOs(); } diff --git a/src/gpu/GrAppliedClip.h b/src/gpu/GrAppliedClip.h index 57314ec7d4..8488dc4d5d 100644 --- a/src/gpu/GrAppliedClip.h +++ b/src/gpu/GrAppliedClip.h @@ -16,8 +16,12 @@ * 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 : public SkNoncopyable { +class GrAppliedClip { 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(); } @@ -52,12 +56,32 @@ 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 diff --git a/src/gpu/GrOpFlushState.cpp b/src/gpu/GrOpFlushState.cpp index 2dddbba2a2..c6f5d38383 100644 --- a/src/gpu/GrOpFlushState.cpp +++ b/src/gpu/GrOpFlushState.cpp @@ -11,13 +11,14 @@ #include "GrPipeline.h" GrOpFlushState::GrOpFlushState(GrGpu* gpu, GrResourceProvider* resourceProvider) - : fGpu(gpu) - , fResourceProvider(resourceProvider) - , fCommandBuffer(nullptr) - , fVertexPool(gpu) - , fIndexPool(gpu) - , fLastIssuedToken(GrDrawOpUploadToken::AlreadyFlushedToken()) - , fLastFlushedToken(0) {} + : fGpu(gpu) + , fResourceProvider(resourceProvider) + , fCommandBuffer(nullptr) + , fVertexPool(gpu) + , fIndexPool(gpu) + , fLastIssuedToken(GrDrawOpUploadToken::AlreadyFlushedToken()) + , fLastFlushedToken(0) + , fOpArgs(nullptr) {} void* GrOpFlushState::makeVertexSpace(size_t vertexSize, int vertexCount, const GrBuffer** buffer, int* startVertex) { diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h index ed77c3b468..d7ed4e0b47 100644 --- a/src/gpu/GrOpFlushState.h +++ b/src/gpu/GrOpFlushState.h @@ -96,22 +96,30 @@ public: fIndexPool.reset(); } -private: + /** 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; }; /** diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp index 845ae4488d..7ab5cbfac6 100644 --- a/src/gpu/GrPipeline.cpp +++ b/src/gpu/GrPipeline.cpp @@ -24,27 +24,31 @@ 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; @@ -86,7 +90,7 @@ GrPipelineOptimizations GrPipeline::init(const InitArgs& args) { fNumColorProcessors = args.fProcessors->numColorFragmentProcessors() - colorFPsToEliminate; int numTotalProcessors = fNumColorProcessors + args.fProcessors->numCoverageFragmentProcessors(); - if (args.fAppliedClip->clipCoverageFragmentProcessor()) { + if (args.fAppliedClip && args.fAppliedClip->clipCoverageFragmentProcessor()) { ++numTotalProcessors; } fFragmentProcessors.reset(numTotalProcessors); @@ -101,8 +105,10 @@ GrPipelineOptimizations GrPipeline::init(const InitArgs& args) { const GrFragmentProcessor* fp = args.fProcessors->coverageFragmentProcessor(i); fFragmentProcessors[currFPIdx].reset(fp); } - if (const GrFragmentProcessor* fp = args.fAppliedClip->clipCoverageFragmentProcessor()) { - fFragmentProcessors[currFPIdx].reset(fp); + if (args.fAppliedClip) { + 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. @@ -118,10 +124,6 @@ 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; } diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h index f5b8fe9cf0..4c439433f5 100644 --- a/src/gpu/GrPrimitiveProcessor.h +++ b/src/gpu/GrPrimitiveProcessor.h @@ -70,11 +70,6 @@ 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 @@ -87,8 +82,6 @@ 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; diff --git a/src/gpu/GrProcessorSet.cpp b/src/gpu/GrProcessorSet.cpp index c4b82621d1..94e2004546 100644 --- a/src/gpu/GrProcessorSet.cpp +++ b/src/gpu/GrProcessorSet.cpp @@ -38,6 +38,44 @@ 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, diff --git a/src/gpu/GrProcessorSet.h b/src/gpu/GrProcessorSet.h index 8203491435..18a52fd9b7 100644 --- a/src/gpu/GrProcessorSet.h +++ b/src/gpu/GrProcessorSet.h @@ -20,13 +20,15 @@ class GrProcessorSet : private SkNoncopyable { public: GrProcessorSet(GrPaint&& paint); - ~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(); - } - } + ~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); } int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; } int numCoverageFragmentProcessors() const { @@ -50,6 +52,9 @@ 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. */ @@ -156,7 +161,8 @@ private: enum Flags : uint16_t { kUseDistanceVectorField_Flag = 0x1, kDisableOutputConversionToSRGB_Flag = 0x2, - kAllowSRGBInputs_Flag = 0x4 + kAllowSRGBInputs_Flag = 0x4, + kPendingExecution_Flag = 0x8 }; const GrXPFactory* fXPFactory = nullptr; diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index bd73c8bc66..70d4485468 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -507,22 +507,17 @@ bool GrRenderTargetContext::drawFilledRect(const GrClip& clip, return true; } - GrAAType aaType; - - if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) { + if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() && + (!ss || ss->isDisabled(false))) { InstancedRendering* ir = this->getOpList()->instancedRendering(); - std::unique_ptr<GrDrawOp> op = ir->recordRect(croppedRect, viewMatrix, paint.getColor(), aa, - fInstancedPipelineInfo, &aaType); + std::unique_ptr<GrDrawOp> op = ir->recordRect(croppedRect, viewMatrix, std::move(paint), aa, + fInstancedPipelineInfo); if (op) { - GrPipelineBuilder pipelineBuilder(std::move(paint), aaType); - if (ss) { - pipelineBuilder.setUserStencil(ss); - } - this->addDrawOp(pipelineBuilder, clip, std::move(op)); + this->addDrawOp(clip, std::move(op)); return true; } } - aaType = this->decideAAType(aa); + GrAAType 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)) { @@ -811,21 +806,18 @@ 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, paint.getColor(), - croppedLocalRect, aa, fInstancedPipelineInfo, - &aaType)); + std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, std::move(paint), + croppedLocalRect, aa, fInstancedPipelineInfo)); if (op) { - GrPipelineBuilder pipelineBuilder(std::move(paint), aaType); - this->addDrawOp(pipelineBuilder, clip, std::move(op)); + this->addDrawOp(clip, std::move(op)); return; } } - aaType = this->decideAAType(aa); + GrAAType aaType = this->decideAAType(aa); if (GrAAType::kCoverage != aaType) { this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect, &croppedLocalRect, nullptr, nullptr, aaType); @@ -833,10 +825,10 @@ void GrRenderTargetContext::fillRectToRect(const GrClip& clip, } if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) { - std::unique_ptr<GrDrawOp> op = GrAAFillRectOp::MakeWithLocalRect( + std::unique_ptr<GrMeshDrawOp> op = GrAAFillRectOp::MakeWithLocalRect( paint.getColor(), viewMatrix, croppedRect, croppedLocalRect); GrPipelineBuilder pipelineBuilder(std::move(paint), aaType); - this->addDrawOp(pipelineBuilder, clip, std::move(op)); + this->addMeshDrawOp(pipelineBuilder, clip, std::move(op)); return; } @@ -870,21 +862,18 @@ 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, paint.getColor(), - localMatrix, aa, fInstancedPipelineInfo, - &aaType)); + std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, std::move(paint), + localMatrix, aa, fInstancedPipelineInfo)); if (op) { - GrPipelineBuilder pipelineBuilder(std::move(paint), aaType); - this->addDrawOp(pipelineBuilder, clip, std::move(op)); + this->addDrawOp(clip, std::move(op)); return; } } - aaType = this->decideAAType(aa); + GrAAType aaType = this->decideAAType(aa); if (GrAAType::kCoverage != aaType) { this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect, nullptr, &localMatrix, nullptr, aaType); @@ -1024,21 +1013,19 @@ 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, paint.getColor(), aa, - fInstancedPipelineInfo, &aaType)); + std::unique_ptr<GrDrawOp> op( + ir->recordRRect(rrect, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo)); if (op) { - GrPipelineBuilder pipelineBuilder(std::move(paint), aaType); - this->addDrawOp(pipelineBuilder, *clip, std::move(op)); + this->addDrawOp(*clip, std::move(op)); return; } } - aaType = this->decideAAType(aa); + GrAAType aaType = this->decideAAType(aa); if (GrAAType::kCoverage == aaType) { const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps(); std::unique_ptr<GrMeshDrawOp> op = @@ -1103,21 +1090,18 @@ 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, - paint.getColor(), aa, fInstancedPipelineInfo, - &aaType)); + std::unique_ptr<GrDrawOp> op(ir->recordDRRect( + origOuter, origInner, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo)); if (op) { - GrPipelineBuilder pipelineBuilder(std::move(paint), aaType); - this->addDrawOp(pipelineBuilder, clip, std::move(op)); + this->addDrawOp(clip, std::move(op)); return true; } } - aaType = this->decideAAType(aa); + GrAAType aaType = this->decideAAType(aa); GrPrimitiveEdgeType innerEdgeType, outerEdgeType; if (GrAAType::kCoverage == aaType) { @@ -1254,21 +1238,19 @@ 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, paint.getColor(), aa, - fInstancedPipelineInfo, &aaType)); + std::unique_ptr<GrDrawOp> op( + ir->recordOval(oval, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo)); if (op) { - GrPipelineBuilder pipelineBuilder(std::move(paint), aaType); - this->addDrawOp(pipelineBuilder, clip, std::move(op)); + this->addDrawOp(clip, std::move(op)); return; } } - aaType = this->decideAAType(aa); + GrAAType aaType = this->decideAAType(aa); if (GrAAType::kCoverage == aaType) { const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps(); std::unique_ptr<GrMeshDrawOp> op = @@ -1672,21 +1654,60 @@ 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::addDrawOp"); + GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addMeshDrawOp"); // Setup clip SkRect bounds; diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h index fc2fc0e881..acb7f77278 100644 --- a/src/gpu/GrRenderTargetContext.h +++ b/src/gpu/GrRenderTargetContext.h @@ -22,8 +22,8 @@ class GrClip; class GrDrawingManager; class GrDrawOp; class GrFixedClip; -class GrPipelineBuilder; class GrMeshDrawOp; +class GrPipelineBuilder; class GrRenderTarget; class GrRenderTargetContextPriv; class GrRenderTargetOpList; @@ -477,9 +477,8 @@ 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 GrPipelineBuilder&, const GrClip&, std::unique_ptr<GrDrawOp>); - uint32_t addMeshDrawOp(const GrPipelineBuilder&, const GrClip&, - std::unique_ptr<GrMeshDrawOp> op); + uint32_t addDrawOp(const GrClip&, std::unique_ptr<GrDrawOp>); + uint32_t addMeshDrawOp(const GrPipelineBuilder&, const GrClip&, std::unique_ptr<GrMeshDrawOp>); // 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 diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp index ba096dc149..d1aca0c308 100644 --- a/src/gpu/GrRenderTargetOpList.cpp +++ b/src/gpu/GrRenderTargetOpList.cpp @@ -30,10 +30,12 @@ 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) { + : INHERITED(rtp, auditTrail) + , fGpu(SkRef(gpu)) + , fResourceProvider(resourceProvider) + , fLastClipStackGenID(SK_InvalidUniqueID) + , fClipAllocator(fClipAllocatorStorage, sizeof(fClipAllocatorStorage), + sizeof(fClipAllocatorStorage)) { fMaxOpLookback = (options.fMaxOpCombineLookback < 0) ? kDefaultMaxOpLookback : options.fMaxOpCombineLookback; @@ -93,7 +95,17 @@ 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); } } @@ -133,7 +145,17 @@ 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(); @@ -224,8 +246,33 @@ 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) { + GrRenderTargetContext* renderTargetContext, + GrAppliedClip* clip, + const DstTexture* dstTexture) { GrRenderTarget* renderTarget = renderTargetContext ? renderTargetContext->accessRenderTarget() : nullptr; @@ -260,7 +307,7 @@ GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr<GrOp> op, candidate.fOp->uniqueID()); break; } - if (candidate.fOp->combineIfPossible(op.get(), *this->caps())) { + if (this->combineIfPossible(candidate, op.get(), clip, dstTexture)) { GrOP_INFO("\t\tCombining with (%s, B%u)\n", candidate.fOp->name(), candidate.fOp->uniqueID()); GrOP_INFO("\t\t\tCombined op info:\n"); @@ -284,7 +331,10 @@ GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr<GrOp> op, GrOP_INFO("\t\tFirstOp\n"); } GR_AUDIT_TRAIL_OP_RESULT_NEW(fAuditTrail, op); - fRecordedOps.emplace_back(std::move(op), renderTarget); + if (clip) { + clip = fClipAllocator.make<GrAppliedClip>(std::move(*clip)); + } + fRecordedOps.emplace_back(std::move(op), renderTarget, clip, dstTexture); fRecordedOps.back().fOp->wasRecorded(); fLastFullClearOp = nullptr; fLastFullClearRenderTargetID.makeInvalid(); @@ -312,7 +362,8 @@ void GrRenderTargetOpList::forwardCombine() { candidate.fOp->uniqueID()); break; } - if (op->combineIfPossible(candidate.fOp.get(), *this->caps())) { + if (this->combineIfPossible(fRecordedOps[i], candidate.fOp.get(), + candidate.fAppliedClip, &candidate.fDstTexture)) { 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()); diff --git a/src/gpu/GrRenderTargetOpList.h b/src/gpu/GrRenderTargetOpList.h index ab744f35e6..c44c3416e3 100644 --- a/src/gpu/GrRenderTargetOpList.h +++ b/src/gpu/GrRenderTargetOpList.h @@ -8,9 +8,11 @@ #ifndef GrRenderTargetOpList_DEFINED #define GrRenderTargetOpList_DEFINED +#include "GrAppliedClip.h" #include "GrOpList.h" -#include "GrPrimitiveProcessor.h" #include "GrPathRendering.h" +#include "GrPrimitiveProcessor.h" +#include "SkArenaAlloc.h" #include "SkClipStack.h" #include "SkMatrix.h" #include "SkStringUtils.h" @@ -22,12 +24,14 @@ 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 { @@ -68,7 +72,13 @@ public: const GrCaps* caps() const { return fGpu->caps(); } uint32_t addOp(std::unique_ptr<GrOp> op, GrRenderTargetContext* renderTargetContext) { - this->recordOp(std::move(op), 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); return this->uniqueID(); } @@ -107,23 +117,34 @@ 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*); + GrOp* recordOp(std::unique_ptr<GrOp>, GrRenderTargetContext*, GrAppliedClip* = nullptr, + const DstTexture* = nullptr); void forwardCombine(); // Used only via GrRenderTargetContextPriv. void clearStencilClip(const GrFixedClip&, bool insideStencilMask, GrRenderTargetContext*); - 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; + // 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); GrClearOp* fLastFullClearOp = nullptr; GrGpuResource::UniqueID fLastFullClearRenderTargetID = GrGpuResource::UniqueID::InvalidID(); @@ -139,6 +160,11 @@ private: int32_t fLastClipStackGenID; SkIRect fLastDevClipBounds; + SkSTArray<256, RecordedOp, true> fRecordedOps; + + char fClipAllocatorStorage[4096]; + SkArenaAlloc fClipAllocator; + typedef GrOpList INHERITED; }; diff --git a/src/gpu/GrTextureOpList.cpp b/src/gpu/GrTextureOpList.cpp index d396b2a5ea..2a021d231a 100644 --- a/src/gpu/GrTextureOpList.cpp +++ b/src/gpu/GrTextureOpList.cpp @@ -50,6 +50,7 @@ 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); } } @@ -61,6 +62,7 @@ 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); } diff --git a/src/gpu/GrXferProcessor.cpp b/src/gpu/GrXferProcessor.cpp index 4d877d6b27..32ab45c65e 100644 --- a/src/gpu/GrXferProcessor.cpp +++ b/src/gpu/GrXferProcessor.cpp @@ -176,14 +176,6 @@ 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; @@ -193,7 +185,6 @@ bool GrXPFactory::WillNeedDstTexture(const GrXPFactory* factory, const GrCaps& c } else { result = GrPorterDuffXPFactory::WillSrcOverNeedDstTexture(caps, analysis); } - SkASSERT(!(result && !WillReadDst(factory, analysis))); return result; } @@ -204,6 +195,14 @@ 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, diff --git a/src/gpu/GrXferProcessor.h b/src/gpu/GrXferProcessor.h index 7f3fd30e8d..35ce5fa4a2 100644 --- a/src/gpu/GrXferProcessor.h +++ b/src/gpu/GrXferProcessor.h @@ -65,9 +65,7 @@ public: } DstTexture(GrTexture* texture, const SkIPoint& offset) - : fTexture(SkSafeRef(texture)) - , fOffset(offset) { - } + : fTexture(SkSafeRef(texture)), fOffset(texture ? offset : SkIPoint{0, 0}) {} DstTexture& operator=(const DstTexture& other) { fTexture = other.fTexture; @@ -75,6 +73,11 @@ 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; } @@ -84,6 +87,9 @@ public: void setTexture(sk_sp<GrTexture> texture) { fTexture = std::move(texture); + if (!fTexture) { + fOffset = {0, 0}; + } } private: @@ -301,11 +307,6 @@ public: 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. */ @@ -315,13 +316,17 @@ 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, @@ -334,6 +339,7 @@ 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 diff --git a/src/gpu/effects/GrCoverageSetOpXP.h b/src/gpu/effects/GrCoverageSetOpXP.h index 807a2b0fc6..184ef4e56c 100644 --- a/src/gpu/effects/GrCoverageSetOpXP.h +++ b/src/gpu/effects/GrCoverageSetOpXP.h @@ -32,10 +32,6 @@ 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, diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp index 31c42ebfd7..37e4c16765 100644 --- a/src/gpu/effects/GrCustomXfermode.cpp +++ b/src/gpu/effects/GrCustomXfermode.cpp @@ -327,8 +327,6 @@ 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; } diff --git a/src/gpu/effects/GrDisableColorXP.h b/src/gpu/effects/GrDisableColorXP.h index f9206f7c19..78442f4125 100644 --- a/src/gpu/effects/GrDisableColorXP.h +++ b/src/gpu/effects/GrDisableColorXP.h @@ -24,8 +24,6 @@ public: static const GrXPFactory* Get(); private: - bool willReadsDst(const FragmentProcessorAnalysis&) const override { return false; } - constexpr GrDisableColorXPFactory() {} bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override { diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp index 8b35bb996a..f98435515a 100644 --- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp +++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp @@ -759,10 +759,11 @@ GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor( return new PorterDuffXferProcessor(blendFormula); } -bool GrPorterDuffXPFactory::willReadsDst(const FragmentProcessorAnalysis& analysis) const { - BlendFormula colorFormula = gBlendTable[analysis.isOutputColorOpaque()][0][(int)fBlendMode]; +bool GrPorterDuffXPFactory::canCombineOverlappedStencilAndCover(bool colorIsOpaque) const { + // Ignore the effect of coverage here. + BlendFormula colorFormula = gBlendTable[colorIsOpaque][0][(int)fBlendMode]; SkASSERT(kAdd_GrBlendEquation == colorFormula.fBlendEquation); - return (colorFormula.usesDstColor() || analysis.hasCoverage()); + return !colorFormula.usesDstColor(); } bool GrPorterDuffXPFactory::willReadDstInShader(const GrCaps& caps, @@ -869,10 +870,6 @@ 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() || diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.h b/src/gpu/effects/GrPorterDuffXferProcessor.h index dd790e8431..719bd18527 100644 --- a/src/gpu/effects/GrPorterDuffXferProcessor.h +++ b/src/gpu/effects/GrPorterDuffXferProcessor.h @@ -37,14 +37,16 @@ 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 willReadsDst(const FragmentProcessorAnalysis&) const override; + bool canCombineOverlappedStencilAndCover(bool colorIsOpaque) const override; GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, const FragmentProcessorAnalysis&, diff --git a/src/gpu/instanced/GLInstancedRendering.cpp b/src/gpu/instanced/GLInstancedRendering.cpp index 0d2a2ddb9c..bfdb9601f9 100644 --- a/src/gpu/instanced/GLInstancedRendering.cpp +++ b/src/gpu/instanced/GLInstancedRendering.cpp @@ -19,7 +19,8 @@ class GLInstancedRendering::GLOp final : public InstancedRendering::Op { public: DEFINE_OP_CLASS_ID - GLOp(GLInstancedRendering* instRendering) : INHERITED(ClassID(), instRendering) {} + GLOp(GLInstancedRendering* instRendering, GrPaint&& paint) + : INHERITED(ClassID(), std::move(paint), instRendering) {} int numGLCommands() const { return 1 + fNumChangesInGeometry; } private: @@ -60,8 +61,8 @@ inline GrGLGpu* GLInstancedRendering::glGpu() const { return static_cast<GrGLGpu*>(this->gpu()); } -std::unique_ptr<InstancedRendering::Op> GLInstancedRendering::makeOp() { - return std::unique_ptr<Op>(new GLOp(this)); +std::unique_ptr<InstancedRendering::Op> GLInstancedRendering::makeOp(GrPaint&& paint) { + return std::unique_ptr<Op>(new GLOp(this, std::move(paint))); } void GLInstancedRendering::onBeginFlush(GrResourceProvider* rp) { diff --git a/src/gpu/instanced/GLInstancedRendering.h b/src/gpu/instanced/GLInstancedRendering.h index 0088217bb2..d1affba2bd 100644 --- a/src/gpu/instanced/GLInstancedRendering.h +++ b/src/gpu/instanced/GLInstancedRendering.h @@ -33,7 +33,7 @@ private: GrGLGpu* glGpu() const; - std::unique_ptr<Op> makeOp() override; + std::unique_ptr<Op> makeOp(GrPaint&& paint) override; void onBeginFlush(GrResourceProvider*) override; void onDraw(const GrPipeline&, const InstanceProcessor&, const Op*) override; diff --git a/src/gpu/instanced/InstancedRendering.cpp b/src/gpu/instanced/InstancedRendering.cpp index ef2264b0ef..179552c852 100644 --- a/src/gpu/instanced/InstancedRendering.cpp +++ b/src/gpu/instanced/InstancedRendering.cpp @@ -22,32 +22,31 @@ InstancedRendering::InstancedRendering(GrGpu* gpu) } std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect, - const SkMatrix& viewMatrix, GrColor color, - GrAA aa, - const GrInstancedPipelineInfo& info, - GrAAType* aaType) { - return this->recordShape(ShapeType::kRect, rect, viewMatrix, color, rect, aa, info, aaType); + const SkMatrix& viewMatrix, + GrPaint&& paint, GrAA aa, + const GrInstancedPipelineInfo& info) { + return this->recordShape(ShapeType::kRect, rect, viewMatrix, std::move(paint), rect, aa, info); } std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect, - 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); + 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); } std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect, - const SkMatrix& viewMatrix, GrColor color, + const SkMatrix& viewMatrix, + GrPaint&& paint, const SkMatrix& localMatrix, GrAA aa, - const GrInstancedPipelineInfo& info, - GrAAType* aaType) { + const GrInstancedPipelineInfo& info) { 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, color, rect, - aa, info, aaType)) { + if (std::unique_ptr<Op> op = this->recordShape(ShapeType::kRect, rect, viewMatrix, + std::move(paint), rect, aa, info)) { op->getSingleInstance().fInfo |= kLocalMatrix_InfoFlag; op->appendParamsTexel(localMatrix.getScaleX(), localMatrix.getSkewX(), localMatrix.getTranslateX()); @@ -60,39 +59,39 @@ std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect, } std::unique_ptr<GrDrawOp> InstancedRendering::recordOval(const SkRect& oval, - const SkMatrix& viewMatrix, GrColor color, - GrAA aa, - const GrInstancedPipelineInfo& info, - GrAAType* aaType) { - return this->recordShape(ShapeType::kOval, oval, viewMatrix, color, oval, aa, info, aaType); + const SkMatrix& viewMatrix, + GrPaint&& paint, GrAA aa, + const GrInstancedPipelineInfo& info) { + return this->recordShape(ShapeType::kOval, oval, viewMatrix, std::move(paint), oval, aa, info); } std::unique_ptr<GrDrawOp> InstancedRendering::recordRRect(const SkRRect& rrect, - const SkMatrix& viewMatrix, GrColor color, - GrAA aa, - const GrInstancedPipelineInfo& info, - GrAAType* aaType) { + const SkMatrix& viewMatrix, + GrPaint&& paint, GrAA aa, + const GrInstancedPipelineInfo& info) { if (std::unique_ptr<Op> op = - this->recordShape(GetRRectShapeType(rrect), rrect.rect(), viewMatrix, color, - rrect.rect(), aa, info, aaType)) { + this->recordShape(GetRRectShapeType(rrect), rrect.rect(), viewMatrix, + std::move(paint), rrect.rect(), aa, info)) { op->appendRRectParams(rrect); return std::move(op); } return nullptr; } -std::unique_ptr<GrDrawOp> InstancedRendering::recordDRRect( - const SkRRect& outer, const SkRRect& inner, const SkMatrix& viewMatrix, GrColor color, - GrAA aa, const GrInstancedPipelineInfo& info, GrAAType* aaType) { +std::unique_ptr<GrDrawOp> InstancedRendering::recordDRRect(const SkRRect& outer, + const SkRRect& inner, + const SkMatrix& viewMatrix, + GrPaint&& paint, GrAA aa, + const GrInstancedPipelineInfo& info) { 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, color, aa, info, aaType); + return this->recordRRect(outer, viewMatrix, std::move(paint), aa, info); } if (std::unique_ptr<Op> op = - this->recordShape(GetRRectShapeType(outer), outer.rect(), viewMatrix, color, - outer.rect(), aa, info, aaType)) { + this->recordShape(GetRRectShapeType(outer), outer.rect(), viewMatrix, + std::move(paint), outer.rect(), aa, info)) { op->appendRRectParams(outer); ShapeType innerShapeType = GetRRectShapeType(inner); op->fInfo.fInnerShapeTypes |= GetShapeFlag(innerShapeType); @@ -105,28 +104,31 @@ std::unique_ptr<GrDrawOp> InstancedRendering::recordDRRect( } std::unique_ptr<InstancedRendering::Op> InstancedRendering::recordShape( - ShapeType type, const SkRect& bounds, const SkMatrix& viewMatrix, GrColor color, - const SkRect& localRect, GrAA aa, const GrInstancedPipelineInfo& info, GrAAType* aaType) { + ShapeType type, const SkRect& bounds, const SkMatrix& viewMatrix, GrPaint&& paint, + const SkRect& localRect, GrAA aa, const GrInstancedPipelineInfo& info) { SkASSERT(State::kRecordingDraws == fState); if (info.fIsRenderingToFloat && fGpu->caps()->avoidInstancedDrawsToFPTargets()) { return nullptr; } - if (!this->selectAntialiasMode(viewMatrix, aa, info, aaType)) { + GrAAType aaType; + if (!this->selectAntialiasMode(viewMatrix, aa, info, &aaType)) { return nullptr; } - std::unique_ptr<Op> op = this->makeOp(); - op->fInfo.setAAType(*aaType); + GrColor color = paint.getColor(); + std::unique_ptr<Op> op = this->makeOp(std::move(paint)); + 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 @@ -229,9 +231,10 @@ inline bool InstancedRendering::selectAntialiasMode(const SkMatrix& viewMatrix, return false; } -InstancedRendering::Op::Op(uint32_t classID, InstancedRendering* ir) +InstancedRendering::Op::Op(uint32_t classID, GrPaint&& paint, InstancedRendering* ir) : INHERITED(classID) , fInstancedRendering(ir) + , fProcessors(std::move(paint)) , fIsTracked(false) , fNumDraws(1) , fNumChangesInGeometry(0) { @@ -329,20 +332,17 @@ void InstancedRendering::Op::appendParamsTexel(SkScalar x, SkScalar y, SkScalar fInfo.fHasParams = true; } -void InstancedRendering::Op::getFragmentProcessorAnalysisInputs( - FragmentProcessorAnalysisInputs* input) const { - input->colorInput()->setToConstant(this->getSingleInstance().fColor); - +bool InstancedRendering::Op::xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) { + GrProcessorSet::FragmentProcessorAnalysis analysis; + GrPipelineInput coverageInput; if (GrAAType::kCoverage == fInfo.aaType() || (GrAAType::kNone == fInfo.aaType() && !fInfo.isSimpleRects() && fInfo.fCannotDiscard)) { - input->coverageInput()->setToUnknown(); + coverageInput = GrPipelineInput(); } else { - input->coverageInput()->setToSolidCoverage(); + coverageInput = GrColor_WHITE; } -} + 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,17 +363,23 @@ void InstancedRendering::Op::applyPipelineOptimizations( } GrColor overrideColor; - if (optimizations.getOverrideColorIfSet(&overrideColor)) { + if (analysis.initialColorProcessorsToEliminate(&overrideColor)) { SkASSERT(State::kRecordingDraws == fInstancedRendering->fState); - this->getSingleInstance().fColor = overrideColor; + this->getSingleDraw().fInstance.fColor = overrideColor; } - fInfo.fUsesLocalCoords = optimizations.readsLocalCoords(); - fInfo.fCannotTweakAlphaForCoverage = !optimizations.canTweakAlphaForCoverage(); + fInfo.fCannotTweakAlphaForCoverage = + !analysis.isCompatibleWithCoverageAsAlpha() || + !GrXPFactory::CompatibleWithCoverageAsAlpha(fProcessors.xpFactory(), + analysis.isOutputColorOpaque()); + + fInfo.fUsesLocalCoords = analysis.usesLocalCoords(); + return GrXPFactory::WillNeedDstTexture(fProcessors.xpFactory(), caps, analysis); } void InstancedRendering::Op::wasRecorded() { SkASSERT(!fIsTracked); fInstancedRendering->fTrackedOps.addToTail(this); + fProcessors.makePendingExecution(); fIsTracked = true; } @@ -383,9 +389,7 @@ bool InstancedRendering::Op::onCombineIfPossible(GrOp* other, const GrCaps& caps SkASSERT(fTailDraw); SkASSERT(that->fTailDraw); - if (!OpInfo::CanCombine(fInfo, that->fInfo) || - !GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), - that->bounds(), caps)) { + if (!OpInfo::CanCombine(fInfo, that->fInfo) || fProcessors != that->fProcessors) { return false; } @@ -406,7 +410,9 @@ 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; @@ -462,12 +468,40 @@ void InstancedRendering::Op::onExecute(GrOpFlushState* state) { SkASSERT(state->gpu() == fInstancedRendering->gpu()); state->gpu()->handleDirtyContext(); - if (GrXferBarrierType barrierType = this->pipeline()->xferBarrierType(*state->gpu()->caps())) { - state->gpu()->xferBarrier(this->pipeline()->getRenderTarget(), barrierType); - } + 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); + } InstanceProcessor instProc(fInfo, fInstancedRendering->fParamsBuffer.get()); - fInstancedRendering->onDraw(*this->pipeline(), instProc, this); + fInstancedRendering->onDraw(pipeline, instProc, this); } void InstancedRendering::endFlush() { diff --git a/src/gpu/instanced/InstancedRendering.h b/src/gpu/instanced/InstancedRendering.h index 778e8b4511..c2db768121 100644 --- a/src/gpu/instanced/InstancedRendering.h +++ b/src/gpu/instanced/InstancedRendering.h @@ -46,35 +46,31 @@ public: * draws between beginFlush() and endFlush(). */ std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&, - GrColor, GrAA, - const GrInstancedPipelineInfo&, - GrAAType*); + GrPaint&&, GrAA, + const GrInstancedPipelineInfo&); std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&, - GrColor, const SkRect& localRect, - GrAA, const GrInstancedPipelineInfo&, - GrAAType*); + GrPaint&&, const SkRect& localRect, + GrAA, + const GrInstancedPipelineInfo&); std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&, - GrColor, const SkMatrix& localMatrix, - GrAA, const GrInstancedPipelineInfo&, - GrAAType*); + GrPaint&&, + const SkMatrix& localMatrix, GrAA, + const GrInstancedPipelineInfo&); std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordOval(const SkRect&, const SkMatrix&, - GrColor, GrAA, - const GrInstancedPipelineInfo&, - GrAAType*); + GrPaint&&, GrAA, + const GrInstancedPipelineInfo&); std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRRect(const SkRRect&, const SkMatrix&, - GrColor, GrAA, - const GrInstancedPipelineInfo&, - GrAAType*); + GrPaint&&, GrAA, + const GrInstancedPipelineInfo&); std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordDRRect(const SkRRect& outer, const SkRRect& inner, - const SkMatrix&, GrColor, GrAA, - const GrInstancedPipelineInfo&, - GrAAType*); + const SkMatrix&, GrPaint&&, GrAA, + const GrInstancedPipelineInfo&); /** * Compiles all recorded draws into GPU buffers and allows the client to begin flushing the @@ -122,7 +118,6 @@ protected: fIsTracked, fNumDraws, fNumChangesInGeometry); - string.append(DumpPipelineInfo(*this->pipeline())); string.append(INHERITED::dumpInfo()); return string; } @@ -140,27 +135,32 @@ 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, InstancedRendering* ir); + Op(uint32_t classID, GrPaint&&, InstancedRendering*); InstancedRendering* const fInstancedRendering; OpInfo fInfo; SkScalar fPixelLoad; + GrProcessorSet fProcessors; SkSTArray<5, ParamsTexel, true> fParams; - bool fIsTracked; + bool fIsTracked : 1; + bool fDrawColorsAreOpaque : 1; + bool fDrawColorsAreSame : 1; 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,15 +190,14 @@ private: }; std::unique_ptr<Op> SK_WARN_UNUSED_RESULT recordShape(ShapeType, const SkRect& bounds, - const SkMatrix& viewMatrix, GrColor, + const SkMatrix& viewMatrix, GrPaint&&, const SkRect& localRect, GrAA aa, - const GrInstancedPipelineInfo&, - GrAAType*); + const GrInstancedPipelineInfo&); bool selectAntialiasMode(const SkMatrix& viewMatrix, GrAA aa, const GrInstancedPipelineInfo&, GrAAType*); - virtual std::unique_ptr<Op> makeOp() = 0; + virtual std::unique_ptr<Op> makeOp(GrPaint&&) = 0; const sk_sp<GrGpu> fGpu; State fState; diff --git a/src/gpu/ops/GrDrawOp.h b/src/gpu/ops/GrDrawOp.h index 62a16887ee..0458370bcd 100644 --- a/src/gpu/ops/GrDrawOp.h +++ b/src/gpu/ops/GrDrawOp.h @@ -12,6 +12,8 @@ #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 @@ -56,22 +58,27 @@ public: GrDrawOp(uint32_t classID) : INHERITED(classID) {} - void initPipeline(const GrPipeline::InitArgs& args) { - this->applyPipelineOptimizations(fPipeline.init(args)); - } + /** + * 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; /** - * Performs analysis of the fragment processors in GrProcessorSet and GrAppliedClip using the - * initial color and coverage from this op's geometry processor. + * 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. */ - 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); - } + virtual bool xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*) = 0; protected: static SkString DumpPipelineInfo(const GrPipeline& pipeline) { @@ -105,53 +112,20 @@ 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 diff --git a/src/gpu/ops/GrDrawPathOp.cpp b/src/gpu/ops/GrDrawPathOp.cpp index 85fb1473d5..fa08ae6d54 100644 --- a/src/gpu/ops/GrDrawPathOp.cpp +++ b/src/gpu/ops/GrDrawPathOp.cpp @@ -6,36 +6,78 @@ */ #include "GrDrawPathOp.h" - +#include "GrAppliedClip.h" +#include "GrRenderTargetContext.h" #include "GrRenderTargetPriv.h" +#include "SkTemplates.h" -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()); -} +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) {} 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) { - GrProgramDesc desc; + GrColor color = this->color(); + GrPipeline pipeline; + GrPipelineOptimizations optimizations = this->initPipeline(*state, &pipeline); + optimizations.getOverrideColorIfSet(&color); + sk_sp<GrPathProcessor> pathProc(GrPathProcessor::Create(color, this->viewMatrix())); - sk_sp<GrPathProcessor> pathProc( - GrPathProcessor::Create(this->color(), this->viewMatrix())); - state->gpu()->pathRendering()->drawPath(*this->pipeline(), *pathProc, - this->stencilPassSettings(), fPath.get()); + GrStencilSettings stencil; + init_stencil_pass_settings(*state, this->fillType(), &stencil); + state->gpu()->pathRendering()->drawPath(pipeline, *pathProc, stencil, fPath.get()); } +////////////////////////////////////////////////////////////////////////////// + SkString GrDrawPathRangeOp::dumpInfo() const { SkString string; string.printf("RANGE: 0x%p COUNTS: [", fPathRange.get()); @@ -44,16 +86,15 @@ 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, GrColor color, GrPathRendering::FillType fill, - GrPathRange* range, const InstanceData* instanceData, + SkScalar y, GrPaint&& paint, GrPathRendering::FillType fill, + GrAA aa, GrPathRange* range, const InstanceData* instanceData, const SkRect& bounds) - : INHERITED(ClassID(), viewMatrix, color, fill) + : INHERITED(ClassID(), viewMatrix, std::move(paint), fill, aa) , fPathRange(range) , fTotalPathCount(instanceData->count()) , fScale(scale) { @@ -61,6 +102,10 @@ 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() || @@ -68,7 +113,7 @@ bool GrDrawPathRangeOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) { this->color() != that->color() || !this->viewMatrix().cheapEqualTo(that->viewMatrix())) { return false; } - if (!GrPipeline::AreEqual(*this->pipeline(), *that->pipeline())) { + if (this->processors() != that->processors()) { return false; } switch (fDraws.head()->fInstanceData->transformType()) { @@ -98,11 +143,20 @@ 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() || this->xpReadsDst()) { + 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)) { return false; } - SkASSERT(!that->xpReadsDst()); fTotalPathCount += that->fTotalPathCount; while (Draw* head = that->fDraws.head()) { Draw* draw = fDraws.addToTail(); @@ -129,11 +183,15 @@ 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(*this->pipeline(), + state->gpu()->pathRendering()->drawPaths(pipeline, *pathProc, - this->stencilPassSettings(), + stencil, fPathRange.get(), instances.indices(), GrPathRange::kU16_PathIndexType, @@ -159,9 +217,9 @@ void GrDrawPathRangeOp::onExecute(GrOpFlushState* state) { } SkASSERT(idx == fTotalPathCount); - state->gpu()->pathRendering()->drawPaths(*this->pipeline(), + state->gpu()->pathRendering()->drawPaths(pipeline, *pathProc, - this->stencilPassSettings(), + stencil, fPathRange.get(), indexStorage, GrPathRange::kU16_PathIndexType, diff --git a/src/gpu/ops/GrDrawPathOp.h b/src/gpu/ops/GrDrawPathOp.h index ffe8768cc0..cf3ce2f11c 100644 --- a/src/gpu/ops/GrDrawPathOp.h +++ b/src/gpu/ops/GrDrawPathOp.h @@ -14,45 +14,53 @@ #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, GrColor initialColor, - GrPathRendering::FillType fill) - : INHERITED(classID), fViewMatrix(viewMatrix), fColor(initialColor), fFillType(fill) {} - - const GrStencilSettings& stencilPassSettings() const { - SkASSERT(!fStencilPassSettings.isDisabled()); // This shouldn't be called before onPrepare. - return fStencilPassSettings; + 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)); } + void wasRecorded() override { fProcessorSet.makePendingExecution(); } + protected: const SkMatrix& viewMatrix() const { return fViewMatrix; } - GrColor color() const { return fColor; } + GrColor color() const { return fAnalysis.inputColor(); } GrPathRendering::FillType fillType() const { return fFillType; } - bool xpReadsDst() const { return fXPReadsDst; } - -private: - void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override { - input->colorInput()->setToConstant(fColor); - input->coverageInput()->setToSolidCoverage(); + 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; } - - void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override { - optimizations.getOverrideColorIfSet(&fColor); - fXPReadsDst = optimizations.xpReadsDst(); + const GrProcessorSet::FragmentProcessorAnalysis& fragmentProcessorAnalysis() const { + SkASSERT(fAnalysis.isInitializedWithProcessorSet()); + return fAnalysis; } - void onPrepare(GrOpFlushState*) override; // Initializes fStencilPassSettings. +private: + void onPrepare(GrOpFlushState*) final {} SkMatrix fViewMatrix; - GrColor fColor; + GrProcessorSet fProcessorSet; + GrProcessorSet::FragmentProcessorAnalysis fAnalysis; GrPathRendering::FillType fFillType; - GrStencilSettings fStencilPassSettings; - bool fXPReadsDst; + GrAA fAA; typedef GrDrawOp INHERITED; }; @@ -61,9 +69,9 @@ class GrDrawPathOp final : public GrDrawPathOpBase { public: DEFINE_OP_CLASS_ID - static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, GrColor color, - const GrPath* path) { - return std::unique_ptr<GrDrawOp>(new GrDrawPathOp(viewMatrix, color, path)); + 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)); } const char* name() const override { return "DrawPath"; } @@ -71,8 +79,9 @@ public: SkString dumpInfo() const override; private: - GrDrawPathOp(const SkMatrix& viewMatrix, GrColor color, const GrPath* path) - : GrDrawPathOpBase(ClassID(), viewMatrix, color, path->getFillType()), fPath(path) { + GrDrawPathOp(const SkMatrix& viewMatrix, GrPaint&& paint, GrAA aa, const GrPath* path) + : GrDrawPathOpBase(ClassID(), viewMatrix, std::move(paint), path->getFillType(), aa) + , fPath(path) { this->setTransformedBounds(path->getBounds(), viewMatrix, HasAABloat::kNo, IsZeroArea::kNo); } @@ -152,11 +161,12 @@ public: }; static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x, - SkScalar y, GrColor color, GrPathRendering::FillType fill, + SkScalar y, GrPaint&& paint, + GrPathRendering::FillType fill, GrAA aa, GrPathRange* range, const InstanceData* instanceData, const SkRect& bounds) { - return std::unique_ptr<GrDrawOp>(new GrDrawPathRangeOp(viewMatrix, scale, x, y, color, fill, - range, instanceData, bounds)); + return std::unique_ptr<GrDrawOp>(new GrDrawPathRangeOp( + viewMatrix, scale, x, y, std::move(paint), fill, aa, range, instanceData, bounds)); } const char* name() const override { return "DrawPathRange"; } @@ -165,7 +175,7 @@ public: private: GrDrawPathRangeOp(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x, SkScalar y, - GrColor color, GrPathRendering::FillType fill, GrPathRange* range, + GrPaint&& paint, GrPathRendering::FillType fill, GrAA aa, GrPathRange* range, const InstanceData* instanceData, const SkRect& bounds); TransformType transformType() const { return fDraws.head()->fInstanceData->transformType(); } diff --git a/src/gpu/ops/GrMeshDrawOp.cpp b/src/gpu/ops/GrMeshDrawOp.cpp index 5d83bd5364..59335d41db 100644 --- a/src/gpu/ops/GrMeshDrawOp.cpp +++ b/src/gpu/ops/GrMeshDrawOp.cpp @@ -60,6 +60,9 @@ 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; diff --git a/src/gpu/ops/GrMeshDrawOp.h b/src/gpu/ops/GrMeshDrawOp.h index a7d312f151..4cf7c52672 100644 --- a/src/gpu/ops/GrMeshDrawOp.h +++ b/src/gpu/ops/GrMeshDrawOp.h @@ -15,6 +15,7 @@ #include "SkTLList.h" +class GrCaps; class GrOpFlushState; /** @@ -24,9 +25,39 @@ class GrMeshDrawOp : public GrDrawOp { public: class Target; - GrMeshDrawOp(uint32_t classID); + /** + * 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); + /** 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 { @@ -62,7 +93,39 @@ 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; @@ -82,7 +145,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; diff --git a/src/gpu/ops/GrOp.h b/src/gpu/ops/GrOp.h index c1bf7f7555..ef752b5d0c 100644 --- a/src/gpu/ops/GrOp.h +++ b/src/gpu/ops/GrOp.h @@ -11,6 +11,7 @@ #include "../private/SkAtomics.h" #include "GrGpuResource.h" #include "GrNonAtomicRef.h" +#include "GrXferProcessor.h" #include "SkMatrix.h" #include "SkRect.h" #include "SkString.h" diff --git a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp index 3b3816329d..4c2edf408f 100644 --- a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp +++ b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp @@ -145,22 +145,10 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) { std::move(coverOp)); } } else { - static constexpr GrUserStencilSettings kCoverPass( - GrUserStencilSettings::StaticInit< - 0x0000, - GrUserStencilTest::kNotEqual, - 0xffff, - GrUserStencilOp::kZero, - GrUserStencilOp::kKeep, - 0xffff>() - ); - + GrAA aa = GrBoolToAA(GrAATypeIsHW(args.fAAType)); std::unique_ptr<GrDrawOp> 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)); + GrDrawPathOp::Make(viewMatrix, std::move(args.fPaint), aa, path.get()); + args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op)); } return true; diff --git a/src/gpu/text/GrStencilAndCoverTextContext.cpp b/src/gpu/text/GrStencilAndCoverTextContext.cpp index acd426787b..e572e5d633 100644 --- a/src/gpu/text/GrStencilAndCoverTextContext.cpp +++ b/src/gpu/text/GrStencilAndCoverTextContext.cpp @@ -605,24 +605,13 @@ 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, - grPaint.getColor(), GrPathRendering::kWinding_FillType, glyphs.get(), + std::move(grPaint), GrPathRendering::kWinding_FillType, runAA, glyphs.get(), fInstanceData.get(), bounds); - // 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)); + renderTargetContext->addDrawOp(clip, std::move(op)); } if (fFallbackTextBlob) { diff --git a/tests/GpuSampleLocationsTest.cpp b/tests/GpuSampleLocationsTest.cpp index 8808b1d8cb..5cb9b606db 100644 --- a/tests/GpuSampleLocationsTest.cpp +++ b/tests/GpuSampleLocationsTest.cpp @@ -96,14 +96,12 @@ 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); } diff --git a/tests/GrPorterDuffTest.cpp b/tests/GrPorterDuffTest.cpp index ddca03a497..de1843813a 100644 --- a/tests/GrPorterDuffTest.cpp +++ b/tests/GrPorterDuffTest.cpp @@ -9,7 +9,6 @@ #if SK_SUPPORT_GPU -#include "GrAppliedClip.h" #include "GrContextFactory.h" #include "GrContextOptions.h" #include "GrGpu.h" @@ -68,7 +67,10 @@ public: XPInfo(skiatest::Reporter* reporter, SkBlendMode xfermode, const GrCaps& caps, const GrProcessorSet::FragmentProcessorAnalysis& analysis) { const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(xfermode); - fReadsDst = GrXPFactory::WillReadDst(xpf, analysis); + // The GrXPFactory query assumes no coverage. + fCanCombineOverlappedStencilAndCover = + !analysis.hasCoverage() && GrXPFactory::CanCombineOverlappedStencilAndCover( + xpf, analysis.isOutputColorOpaque()); sk_sp<GrXferProcessor> xp(xpf->createXferProcessor(analysis, false, nullptr, caps)); TEST_ASSERT(!GrXPFactory::WillNeedDstTexture(xpf, caps, analysis)); fOptFlags = xp->getOptimizations(analysis); @@ -78,7 +80,7 @@ public: TEST_ASSERT(xp->hasSecondaryOutput() == GrBlendCoeffRefsSrc2(fBlendInfo.fDstBlend)); } - bool fReadsDst; + bool fCanCombineOverlappedStencilAndCover; int fOptFlags; int fPrimaryOutputType; int fSecondaryOutputType; @@ -104,7 +106,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -114,7 +116,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrc: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType); @@ -124,7 +126,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDst: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kIgnoreColor_OptFlag | kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); @@ -135,7 +137,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcOver: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kSAModulate_OutputType == xpi.fSecondaryOutputType); @@ -145,7 +147,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstOver: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -155,7 +157,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcIn: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType); @@ -165,7 +167,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstIn: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kISAModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -175,7 +177,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcOut: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType); @@ -185,7 +187,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstOut: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kSAModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -195,7 +197,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcATop: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kSAModulate_OutputType == xpi.fSecondaryOutputType); @@ -205,7 +207,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstATop: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kISAModulate_OutputType == xpi.fSecondaryOutputType); @@ -215,7 +217,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kXor: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kSAModulate_OutputType == xpi.fSecondaryOutputType); @@ -225,7 +227,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kPlus: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -235,7 +237,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kModulate: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kISCModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -245,7 +247,7 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kScreen: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -273,7 +275,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -283,7 +285,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrc: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType); @@ -293,7 +295,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDst: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kIgnoreColor_OptFlag | kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); @@ -304,7 +306,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcOver: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -314,7 +316,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstOver: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -324,7 +326,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcIn: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType); @@ -334,7 +336,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstIn: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kISAModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -344,7 +346,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcOut: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType); @@ -354,7 +356,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstOut: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -364,7 +366,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcATop: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -374,7 +376,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstATop: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kISAModulate_OutputType == xpi.fSecondaryOutputType); @@ -384,7 +386,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kXor: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -394,7 +396,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kPlus: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -404,7 +406,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kModulate: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kISCModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -414,7 +416,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kScreen: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -443,7 +445,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.fReadsDst); + TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kIgnoreColor_OptFlag == xpi.fOptFlags); TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -453,7 +455,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.fReadsDst); + TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -463,7 +465,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kIgnoreColor_OptFlag | kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); @@ -474,7 +476,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -484,7 +486,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -494,7 +496,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -504,7 +506,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -514,7 +516,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -524,7 +526,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -534,7 +536,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -544,7 +546,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -554,7 +556,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -564,7 +566,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -574,7 +576,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -584,7 +586,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -614,7 +616,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -624,7 +626,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrc: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -634,7 +636,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDst: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kIgnoreColor_OptFlag | kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); @@ -645,7 +647,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcOver: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -655,7 +657,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstOver: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -665,7 +667,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcIn: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -675,7 +677,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstIn: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kIgnoreColor_OptFlag | kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); @@ -686,7 +688,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcOut: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -696,7 +698,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstOut: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -706,7 +708,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kSrcATop: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -716,7 +718,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kDstATop: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -726,7 +728,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kXor: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -736,7 +738,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kPlus: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -746,7 +748,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kModulate: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags); TEST_ASSERT(kISCModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -756,7 +758,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const TEST_ASSERT(xpi.fBlendInfo.fWriteColor); break; case SkBlendMode::kScreen: - TEST_ASSERT(xpi.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -786,7 +788,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr switch (xfermode) { case SkBlendMode::kClear: - TEST_ASSERT(!xpi.fReadsDst); + TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kIgnoreColor_OptFlag == xpi.fOptFlags); TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -796,7 +798,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.fReadsDst); + TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -806,7 +808,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kIgnoreColor_OptFlag | kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); @@ -817,7 +819,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.fReadsDst); + TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -827,7 +829,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -837,7 +839,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -847,7 +849,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT((kIgnoreColor_OptFlag | kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); @@ -858,7 +860,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -868,7 +870,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.fReadsDst); + TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kIgnoreColor_OptFlag == xpi.fOptFlags); TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -878,7 +880,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -888,7 +890,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -898,7 +900,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -908,7 +910,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -918,7 +920,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -928,7 +930,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.fReadsDst); + TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover); TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags); TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); @@ -961,15 +963,14 @@ 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; - GrAppliedClip clip; - testLCDCoverageOp.analyzeProcessors(&analysis, GrProcessorSet(GrPaint()), &clip, caps); + testLCDCoverageOp.analyzeProcessors(&analysis, GrProcessorSet(GrPaint()), nullptr, caps); SkASSERT(analysis.hasKnownOutputColor()); SkASSERT(analysis.hasLCDCoverage()); @@ -983,8 +984,6 @@ static void test_lcd_coverage_fallback_case(skiatest::Reporter* reporter, const return; } - TEST_ASSERT(GrXPFactory::WillReadDst(xpf, analysis)); - xp->getOptimizations(analysis); GrXferProcessor::BlendInfo blendInfo; |