blob: ee8ff9cf6a988de7aa3993a1d28ca51ad3c7f389 [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 GrTessellatePathOp_DEFINED
#define GrTessellatePathOp_DEFINED
#include "src/gpu/ops/GrDrawOp.h"
class GrAppliedHardClip;
class GrFillPathShader;
class GrStencilPathShader;
// Renders paths using the classic Red Book "stencil, then cover" method. Curves get linearized by
// GPU tessellation shaders. This Op doesn't apply analytic AA, so it requires a render target that
// supports either MSAA or mixed samples if AA is desired.
class GrTessellatePathOp : public GrDrawOp {
public:
enum class Flags {
kNone = 0,
kStencilOnly = (1 << 0),
kWireframe = (1 << 1)
};
private:
DEFINE_OP_CLASS_ID
GrTessellatePathOp(const SkMatrix& viewMatrix, const SkPath& path, GrPaint&& paint,
GrAAType aaType, Flags flags = Flags::kNone)
: GrDrawOp(ClassID())
, fFlags(flags)
, fViewMatrix(viewMatrix)
, fPath(path)
, fAAType(aaType)
, fColor(paint.getColor4f())
, fProcessors(std::move(paint)) {
SkRect devBounds;
fViewMatrix.mapRect(&devBounds, path.getBounds());
this->setBounds(devBounds, HasAABloat(GrAAType::kCoverage == fAAType), IsHairline::kNo);
}
const char* name() const override { return "GrTessellatePathOp"; }
void visitProxies(const VisitProxyFunc& fn) const override { fProcessors.visitProxies(fn); }
GrProcessorSet::Analysis finalize(const GrCaps& caps, const GrAppliedClip* clip,
bool hasMixedSampledCoverage,
GrClampType clampType) override {
return fProcessors.finalize(
fColor, GrProcessorAnalysisCoverage::kNone, clip, &GrUserStencilSettings::kUnused,
hasMixedSampledCoverage, caps, clampType, &fColor);
}
FixedFunctionFlags fixedFunctionFlags() const override;
void onPrePrepare(GrRecordingContext*,
const GrSurfaceProxyView* outputView,
GrAppliedClip*,
const GrXferProcessor::DstProxyView&) override;
void onPrepare(GrOpFlushState* state) override;
void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
void drawStencilPass(GrOpFlushState*);
void drawCoverPass(GrOpFlushState*);
const Flags fFlags;
const SkMatrix fViewMatrix;
const SkPath fPath;
const GrAAType fAAType;
SkPMColor4f fColor;
GrProcessorSet fProcessors;
// These path shaders get created during onPrepare for drawing the below path vertex data.
//
// If fFillPathShader is null, then we just stencil the full path using fStencilPathShader and
// fCubicInstanceBuffer, and then fill it using a simple bounding box.
//
// If fFillPathShader is not null, then we fill the path using it plus cubic hulls from
// fCubicInstanceBuffer instead of a bounding box.
//
// If fFillPathShader is not null and fStencilPathShader *is* null, then the vertex data
// contains non-overlapping path geometry that can be drawn directly to the final render target.
// We only need to stencil curves from fCubicInstanceBuffer, and then draw the rest of the path
// directly.
GrStencilPathShader* fStencilPathShader = nullptr;
GrFillPathShader* fFillPathShader = nullptr;
// The "path vertex data" is made up of cubic wedges or inner polygon triangles (either red book
// style or fully tessellated). The geometry is generated by
// GrPathParser::EmitCenterWedgePatches, GrPathParser::EmitInnerPolygonTriangles,
// or GrTriangulator::PathToTriangles.
sk_sp<const GrBuffer> fPathVertexBuffer;
int fBasePathVertex;
int fPathVertexCount;
// The cubic instance buffer defines standalone cubics to tessellate into the stencil buffer, in
// addition to the above path geometry.
sk_sp<const GrBuffer> fCubicInstanceBuffer;
int fBaseCubicInstance;
int fCubicInstanceCount;
friend class GrOpMemoryPool; // For ctor.
};
GR_MAKE_BITFIELD_CLASS_OPS(GrTessellatePathOp::Flags);
#endif