66 : fPrimitiveType(primitiveType)
68 , fVertexStride(sizeof(
SkPoint))
73 this->allocNewBuffers();
77 this->createMeshAndPutBackReserve();
84 if (!this->ensureSpace(1)) {
88 if (!this->isHairline()) {
89 fSubpathIndexStart = this->currentIndex();
90 fSubpathStartPoint =
p;
95 void addLine(
const SkPoint pts[]) {
96 if (!this->ensureSpace(1, this->indexScale(), &pts[0])) {
100 if (this->isIndexed()) {
101 uint16_t prevIdx = this->currentIndex() - 1;
102 this->appendCountourEdgeIndices(prevIdx);
104 *(fCurVert++) = pts[1];
115 uint16_t firstQPtIdx = this->currentIndex() - 1;
117 pts[0], pts[1], pts[2], srcSpaceTolSqd, &fCurVert,
119 if (this->isIndexed()) {
120 for (uint16_t
i = 0;
i < numPts; ++
i) {
121 this->appendCountourEdgeIndices(firstQPtIdx +
i);
131 this->addQuad(quadPts +
i * 2, srcSpaceTolSqd, srcSpaceTol);
143 uint16_t firstCPtIdx = this->currentIndex() - 1;
145 pts[0], pts[1], pts[2], pts[3], srcSpaceTolSqd, &fCurVert,
147 if (this->isIndexed()) {
148 for (uint16_t
i = 0;
i < numPts; ++
i) {
149 this->appendCountourEdgeIndices(firstCPtIdx +
i);
155 SkScalar srcSpaceTolSqd = srcSpaceTol * srcSpaceTol;
165 this->moveTo(pts[0]);
171 this->addConic(iter.conicWeight(), pts, srcSpaceTolSqd, srcSpaceTol);
174 this->addQuad(pts, srcSpaceTolSqd, srcSpaceTol);
177 this->addCubic(pts, srcSpaceTolSqd, srcSpaceTol);
187 static bool PathHasMultipleSubpaths(
const SkPath&
path) {
208 bool isIndexed()
const {
212 bool isHairline()
const {
216 int indexScale()
const {
217 switch (fPrimitiveType) {
227 uint16_t currentIndex()
const {
return fCurVert - fVertices; }
230 void allocNewBuffers() {
238 static const int kFallbackVerticesPerChunk = 16384;
240 fVertices =
static_cast<SkPoint*
>(fTarget->makeVertexSpaceAtLeast(fVertexStride,
241 kMinVerticesPerChunk,
242 kFallbackVerticesPerChunk,
247 SkDebugf(
"WARNING: Failed to allocate vertex buffer for DefaultPathRenderer.\n");
249 fCurIdx = fIndices =
nullptr;
250 fSubpathIndexStart = 0;
255 if (this->isIndexed()) {
260 const int kFallbackIndicesPerChunk = kFallbackVerticesPerChunk * this->indexScale();
262 fIndices = fTarget->makeIndexSpaceAtLeast(kMinIndicesPerChunk, kFallbackIndicesPerChunk,
266 SkDebugf(
"WARNING: Failed to allocate index buffer for DefaultPathRenderer.\n");
272 fCurVert = fVertices;
274 fSubpathIndexStart = 0;
277 void appendCountourEdgeIndices(uint16_t edgeV0Idx) {
282 if (!this->isHairline()) {
283 *(fCurIdx++) = fSubpathIndexStart;
285 *(fCurIdx++) = edgeV0Idx;
286 *(fCurIdx++) = edgeV0Idx + 1;
290 void createMeshAndPutBackReserve() {
295 int vertexCount = fCurVert - fVertices;
296 int indexCount = fCurIdx - fIndices;
297 SkASSERT(vertexCount <= fVerticesInChunk);
298 SkASSERT(indexCount <= fIndicesInChunk);
302 mesh = fTarget->allocMesh();
303 if (!this->isIndexed()) {
312 fTarget->putBackIndices((
size_t)(fIndicesInChunk - indexCount));
313 fTarget->putBackVertices((
size_t)(fVerticesInChunk - vertexCount), fVertexStride);
320 bool ensureSpace(
int vertsNeeded,
int indicesNeeded = 0,
const SkPoint* lastPoint =
nullptr) {
325 if (fCurVert + vertsNeeded > fVertices + fVerticesInChunk ||
326 fCurIdx + indicesNeeded > fIndices + fIndicesInChunk) {
333 SkASSERT(fSubpathIndexStart < fVerticesInChunk);
336 if (!this->isHairline()) {
337 SkASSERT(fSubpathStartPoint == fVertices[fSubpathIndexStart]);
340 SkASSERT(*(fCurVert - 1) == *lastPoint);
345 this->createMeshAndPutBackReserve();
348 this->allocNewBuffers();
357 if (!this->isHairline()) {
358 *(fCurVert++) = fSubpathStartPoint;
360 *(fCurVert++) = *lastPoint;
369 size_t fVertexStride;
373 int fVerticesInChunk;
382 uint16_t fSubpathIndexStart;
406 return Helper::FactoryHelper<DefaultPathOp>(context, std::move(
paint),
path, tolerance,
407 coverage, viewMatrix, isHairline, aaType,
408 devBounds, stencilSettings);
411 const char*
name()
const override {
return "DefaultPathOp"; }
426 , fHelper(processorSet, aaType, stencilSettings)
430 , fIsHairline(isHairline) {
431 fPaths.emplace_back(PathData{
path, tolerance});
433 HasAABloat aaBloat = (aaType ==
GrAAType::kNone) ? HasAABloat ::kNo : HasAABloat::kYes;
435 isHairline ? IsHairline::kYes : IsHairline::kNo);
451 if (this->isHairline()) {
452 int instanceCount = fPaths.size();
455 bool isIndexed = instanceCount > 1 ||
456 PathGeoBuilder::PathHasMultipleSubpaths(fPaths[0].
fPath);
469 bool usesMSAASurface,
480 : LocalCoords::kUnused_Type);
492 std::move(appliedClip), dstProxyView,
493 gp, this->primType(),
494 renderPassXferBarriers, colorLoadOp);
499 PathGeoBuilder pathGeoBuilder(this->primType(),
target, &
fMeshes);
502 for (
int i = 0;
i < fPaths.size();
i++) {
503 const PathData&
args = fPaths[
i];
504 pathGeoBuilder.addPath(
args.fPath,
args.fTolerance);
513 if (!fProgramInfo ||
fMeshes.empty()) {
525 DefaultPathOp* that = t->
cast<DefaultPathOp>();
526 if (!fHelper.
isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
527 return CombineResult::kCannotCombine;
530 if (this->
color() != that->color()) {
531 return CombineResult::kCannotCombine;
534 if (this->
coverage() != that->coverage()) {
535 return CombineResult::kCannotCombine;
539 return CombineResult::kCannotCombine;
542 if (this->isHairline() != that->isHairline()) {
543 return CombineResult::kCannotCombine;
546 fPaths.push_back_n(that->fPaths.size(), that->fPaths.begin());
547 return CombineResult::kMerged;
550#if defined(GR_TEST_UTILS)
551 SkString onDumpInfo()
const override {
553 fColor.toBytes_RGBA(), fPaths.size());
554 for (
const auto&
path : fPaths) {
555 string.appendf(
"Tolerance: %.2f\n",
path.fTolerance);
557 string += fHelper.dumpInfo();
565 bool isHairline()
const {
return fIsHairline; }
589#if defined(GR_TEST_UTILS)
591GR_DRAW_OP_TEST_DEFINE(DefaultPathOp) {
592 SkMatrix viewMatrix = GrTest::TestMatrix(random);
597 const SkPath&
path = GrTest::TestPath(random);
605 uint8_t
coverage = GrTest::RandomCoverage(random);
607 if (numSamples > 1 && random->nextBool()) {
611 true, aaType,
bounds, GrGetRandomStencil(random, context));
635 uint8_t newCoverage = 0xff;
636 bool isHairline =
false;
647 bool lastPassIsBounds;
654 passes[0] = &userStencilSettings;
656 lastPassIsBounds =
false;
658 if (single_pass_shape(shape)) {
663 passes[0] = &userStencilSettings;
665 lastPassIsBounds =
false;
667 switch (
path.getFillType()) {
675 lastPassIsBounds =
false;
678 lastPassIsBounds =
true;
694 lastPassIsBounds =
false;
697 lastPassIsBounds =
true;
717 viewMatrix, &devBounds);
719 for (
int p = 0;
p < passCount; ++
p) {
720 if (lastPassIsBounds && (
p == passCount-1)) {
731 if (!viewMatrix.
invert(&localMatrix)) {
746 bool stencilPass = stencilOnly || passCount > 1;
752 newCoverage, viewMatrix, isHairline, aaType, devBounds,
757 viewMatrix, isHairline, aaType, devBounds, passes[
p]);
766DefaultPathRenderer::onGetStencilSupport(
const GrStyledShape& shape)
const {
767 if (single_pass_shape(shape)) {
776 args.fShape->style(), *
args.fViewMatrix,
nullptr);
778 if (!(single_pass_shape(*
args.fShape) || isHairline) &&
779 !
args.fProxy->canUseStencil(*
args.fCaps)) {
787 if (!
args.fShape->style().isSimpleFill() && !isHairline) {
793 if (
args.fCaps->avoidLineDraws() && isHairline) {
800bool DefaultPathRenderer::onDrawPath(
const DrawPathArgs&
args) {
802 "DefaultPathRenderer::onDrawPath");
805 return this->internalDrawPath(
806 args.fSurfaceDrawContext, std::move(
args.fPaint), aaType, *
args.fUserStencilSettings,
810void DefaultPathRenderer::onStencilPath(
const StencilPathArgs&
args) {
812 "DefaultPathRenderer::onStencilPath");
820 this->internalDrawPath(
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
#define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename)
#define DEFINE_OP_CLASS_ID
static constexpr GrUserStencilSettings gEOStencilPass(GrUserStencilSettings::StaticInit< 0xffff, GrUserStencilTest::kAlwaysIfInClip, 0xffff, GrUserStencilOp::kInvert, GrUserStencilOp::kKeep, 0xffff >())
static constexpr GrUserStencilSettings gWindColorPass(GrUserStencilSettings::StaticInit< 0x0000, GrUserStencilTest::kLessIfInClip, 0xffff, GrUserStencilOp::kZero, GrUserStencilOp::kZero, 0xffff >())
static constexpr GrUserStencilSettings gInvEOColorPass(GrUserStencilSettings::StaticInit< 0x0000, GrUserStencilTest::kEqualIfInClip, 0xffff, GrUserStencilOp::kZero, GrUserStencilOp::kZero, 0xffff >())
static constexpr GrUserStencilSettings gInvWindColorPass(GrUserStencilSettings::StaticInit< 0x0000, GrUserStencilTest::kEqualIfInClip, 0xffff, GrUserStencilOp::kZero, GrUserStencilOp::kZero, 0xffff >())
static constexpr GrUserStencilSettings gDirectToStencil(GrUserStencilSettings::StaticInit< 0x0000, GrUserStencilTest::kAlwaysIfInClip, 0xffff, GrUserStencilOp::kZero, GrUserStencilOp::kIncMaybeClamp, 0xffff >())
static constexpr GrUserStencilSettings gEOColorPass(GrUserStencilSettings::StaticInit< 0x0000, GrUserStencilTest::kNotEqual, 0xffff, GrUserStencilOp::kZero, GrUserStencilOp::kZero, 0xffff >())
static constexpr GrUserStencilSettings gWindStencilPass(GrUserStencilSettings::StaticInitSeparate< 0xffff, 0xffff, GrUserStencilTest::kAlwaysIfInClip, GrUserStencilTest::kAlwaysIfInClip, 0xffff, 0xffff, GrUserStencilOp::kIncWrap, GrUserStencilOp::kDecWrap, GrUserStencilOp::kKeep, GrUserStencilOp::kKeep, 0xffff, 0xffff >())
GrProcessorAnalysisCoverage
std::function< void(GrSurfaceProxy *, skgpu::Mipmapped)> GrVisitProxyFunc
bool GrIsStrokeHairlineOrEquivalent(const GrStyle &style, const SkMatrix &matrix, SkScalar *outCoverage)
#define SkDEBUGFAIL(message)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
#define INHERITED(method,...)
#define SkScalarRoundToInt(x)
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
static constexpr bool SkToBool(const T &x)
sk_sp< const GrBuffer > fIndexBuffer
sk_sp< const GrBuffer > fVertexBuffer
static const GrDisableColorXPFactory * Get()
friend class GrSimpleMeshDrawOpHelperWithStencil
virtual FixedFunctionFlags fixedFunctionFlags() const
virtual GrProcessorSet::Analysis finalize(const GrCaps &, const GrAppliedClip *, GrClampType)=0
size_t vertexStride() const
virtual GrProgramInfo * programInfo()=0
void createProgramInfo(const GrCaps *caps, SkArenaAlloc *arena, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&appliedClip, const GrDstProxyView &dstProxyView, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
virtual void onCreateProgramInfo(const GrCaps *, SkArenaAlloc *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&, const GrDstProxyView &, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)=0
virtual void onPrepareDraws(GrMeshDrawTarget *)=0
void drawMesh(const GrSimpleMesh &mesh)
void bindPipelineAndScissorClip(const GrProgramInfo &programInfo, const SkRect &drawBounds)
void bindTextures(const GrGeometryProcessor &geomProc, const GrSurfaceProxy &singleGeomProcTexture, const GrPipeline &pipeline)
virtual void onExecute(GrOpFlushState *, const SkRect &chainBounds)=0
static Owner Make(GrRecordingContext *context, Args &&... args)
std::unique_ptr< GrOp > Owner
virtual const char * name() const =0
virtual void visitProxies(const GrVisitProxyFunc &) const
void setBounds(const SkRect &newBounds, HasAABloat aabloat, IsHairline zeroArea)
virtual CombineResult onCombineIfPossible(GrOp *, SkArenaAlloc *, const GrCaps &)
void setXPFactory(const GrXPFactory *xpFactory)
const GrPipeline & pipeline() const
const GrGeometryProcessor & geomProc() const
void visitFPProxies(const GrVisitProxyFunc &func) const
GrProcessorSet::Analysis finalizeProcessors(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, GrProcessorAnalysisColor *geometryColor)
void visitProxies(const GrVisitProxyFunc &func) const
GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const
bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil &that, const GrCaps &, const SkRect &thisBounds, const SkRect &thatBounds, bool ignoreAAType=false) const
bool usesLocalCoords() const
GrProgramInfo * createProgramInfoWithStencil(const GrCaps *, SkArenaAlloc *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&, const GrDstProxyView &, GrGeometryProcessor *, GrPrimitiveType, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
bool isSimpleFill() const
void asPath(SkPath *out) const
bool knownToBeConvex() const
bool inverseFilled() const
const GrStyle & style() const
SkISize backingStoreDimensions() const
static bool CheapEqual(const SkMatrix &a, const SkMatrix &b)
bool invert(SkMatrix *inverse) const
static const SkMatrix & I()
bool hasPerspective() const
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
@ kNoRestriction_StencilSupport
@ kStencilOnly_StencilSupport
static void GetPathDevBounds(const SkPath &path, SkISize devSize, const SkMatrix &matrix, SkRect *bounds)
GrRenderTargetProxy * asRenderTargetProxy()
GrRecordingContext * recordingContext() const
void addDrawOp(const GrClip *, GrOp::Owner, const std::function< WillAddOpFn > &=std::function< WillAddOpFn >())
void stencilRect(const GrClip *clip, const GrUserStencilSettings *ss, GrPaint &&paint, GrAA doStencilMSAA, const SkMatrix &viewMatrix, const SkRect &rect, const SkMatrix *localMatrix=nullptr)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
GrGeometryProcessor * Make(SkArenaAlloc *, const Color &, const Coverage &, const LocalCoords &, const SkMatrix &viewMatrix)
uint32_t generateCubicPoints(const SkPoint &p0, const SkPoint &p1, const SkPoint &p2, const SkPoint &p3, SkScalar tolSqd, SkPoint **points, uint32_t pointsLeft)
uint32_t quadraticPointCount(const SkPoint points[], SkScalar tol)
static const SkScalar kDefaultTolerance
uint32_t cubicPointCount(const SkPoint points[], SkScalar tol)
SkScalar scaleToleranceToSrc(SkScalar devTol, const SkMatrix &viewM, const SkRect &pathBounds)
static const int kMaxPointsPerCurve
uint32_t generateQuadraticPoints(const SkPoint &p0, const SkPoint &p1, const SkPoint &p2, SkScalar tolSqd, SkPoint **points, uint32_t pointsLeft)
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
Optional< SkRect > bounds
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
static const GrUserStencilSettings & kUnused