blob: d78cfb40e2512cebe6fd4a2625ea17dc48a1d1d5 [file] [log] [blame]
/*
* Copyright 2019 Google LLC.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrStencilAtlasOp_DEFINED
#define GrStencilAtlasOp_DEFINED
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/ccpr/GrCCFiller.h"
#include "src/gpu/ccpr/GrCCStroker.h"
#include "src/gpu/ops/GrDrawOp.h"
class GrCCPerFlushResources;
// Renders literal A8 coverage to a CCPR atlas using an intermediate MSAA stencil buffer.
class GrStencilAtlasOp : public GrDrawOp {
public:
DEFINE_OP_CLASS_ID
using FillBatchID = GrCCFiller::BatchID;
using StrokeBatchID = GrCCStroker::BatchID;
// Once all the paths in an atlas have been drawn to the stencil buffer, we make a final pass
// where we draw "resolve" rects over each path whose purpose is to convert winding counts to A8
// coverage.
struct ResolveRectInstance {
int16_t l, t, r, b;
};
// GrDrawOp interface.
const char* name() const override { return "StencilAtlasOp (CCPR)"; }
FixedFunctionFlags fixedFunctionFlags() const override {
return FixedFunctionFlags::kUsesHWAA | FixedFunctionFlags::kUsesStencil;
}
GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
bool hasMixedSampledCoverage, GrClampType) override {
return GrProcessorSet::EmptySetAnalysis();
}
CombineResult onCombineIfPossible(GrOp* other, SkArenaAlloc*, const GrCaps&) override {
// We will only make multiple copy ops if they have different source proxies.
// TODO: make use of texture chaining.
return CombineResult::kCannotCombine;
}
static GrOp::Owner Make(
GrRecordingContext*, sk_sp<const GrCCPerFlushResources>, FillBatchID, StrokeBatchID,
int baseStencilResolveInstance, int endStencilResolveInstance,
const SkISize& drawBounds);
private:
void onPrePrepare(GrRecordingContext*,
const GrSurfaceProxyView& writeView,
GrAppliedClip*,
const GrXferProcessor::DstProxyView&,
GrXferBarrierFlags renderPassXferBarriers,
GrLoadOp colorLoadOp) override {}
void onPrepare(GrOpFlushState*) override {}
void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
void drawResolve(GrOpFlushState*, const GrPipeline&, const GrUserStencilSettings*,
const GrPrimitiveProcessor&, const SkIRect& drawBounds) const;
friend class ::GrOp; // for ctor
GrStencilAtlasOp(sk_sp<const GrCCPerFlushResources> resources, FillBatchID fillBatchID,
StrokeBatchID strokeBatchID, int baseStencilResolveInstance,
int endStencilResolveInstance, const SkISize& drawBounds)
: GrDrawOp(ClassID())
, fResources(std::move(resources))
, fFillBatchID(fillBatchID)
, fStrokeBatchID(strokeBatchID)
, fBaseStencilResolveInstance(baseStencilResolveInstance)
, fEndStencilResolveInstance(endStencilResolveInstance)
, fDrawBounds(drawBounds) {
this->setBounds(SkRect::MakeIWH(fDrawBounds.width(), fDrawBounds.height()),
GrOp::HasAABloat::kNo, GrOp::IsHairline::kNo);
}
const sk_sp<const GrCCPerFlushResources> fResources;
const FillBatchID fFillBatchID;
const StrokeBatchID fStrokeBatchID;
const int fBaseStencilResolveInstance;
const int fEndStencilResolveInstance;
const SkISize fDrawBounds;
int fResolveBaseVertex;
};
#endif