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