Revert "ccpr: Implement stroking with fine triangle strips"
This reverts commit 2f2757fa6ba8134330e05694d08907f6e37abb41.
Reason for revert: issues with DDL
Original change's description:
> ccpr: Implement stroking with fine triangle strips
>
> Implements strokes by linearizing the curve into fine triangle strips
> and interpolating a coverage ramp for edge AA. Each triangle in the
> strip emits either positive or negative coverage, depending on its
> winding direction. Joins and caps are drawn with the existing CCPR
> shaders for triangles and conics.
>
> Conic strokes and non-rigid-body transforms are not yet supported.
>
> Bug: skia:
> Change-Id: I45a819abd64e91c2b62e992587eb85c703e09e77
> Reviewed-on: https://skia-review.googlesource.com/148243
> Commit-Queue: Chris Dalton <csmartdalton@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Reviewed-by: Allan MacKinnon <allanmac@google.com>
TBR=egdaniel@google.com,bsalomon@google.com,robertphillips@google.com,caryclark@google.com,csmartdalton@google.com,reed@google.com,allanmac@google.com
Change-Id: I1980b09976df8275817eaffb6766dbd9fd3e59c7
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/150980
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
index 2ec8379..aed0672 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
@@ -28,82 +28,25 @@
return sk_64_mul(r.height(), r.width());
}
-std::unique_ptr<GrCCDrawPathsOp> GrCCDrawPathsOp::Make(
- GrContext* context, const SkIRect& clipIBounds, const SkMatrix& m, const GrShape& shape,
- GrPaint&& paint) {
- static constexpr int kPathCropThreshold = GrCoverageCountingPathRenderer::kPathCropThreshold;
-
- SkRect conservativeDevBounds;
- m.mapRect(&conservativeDevBounds, shape.bounds());
-
- const SkStrokeRec& stroke = shape.style().strokeRec();
- float strokeDevWidth = 0;
- float conservativeInflationRadius = 0;
- if (!stroke.isFillStyle()) {
- if (stroke.isHairlineStyle()) {
- strokeDevWidth = 1;
- } else {
- SkASSERT(m.isSimilarity()); // Otherwise matrixScaleFactor = m.getMaxScale().
- float matrixScaleFactor = SkVector::Length(m.getScaleX(), m.getSkewY());
- strokeDevWidth = stroke.getWidth() * matrixScaleFactor;
- }
- // Inflate for a minimum stroke width of 1. In some cases when the stroke is less than 1px
- // wide, we may inflate it to 1px and instead reduce the opacity.
- conservativeInflationRadius = SkStrokeRec::GetInflationRadius(
- stroke.getJoin(), stroke.getMiter(), stroke.getCap(), SkTMax(strokeDevWidth, 1.f));
- conservativeDevBounds.outset(conservativeInflationRadius, conservativeInflationRadius);
- }
-
- std::unique_ptr<GrCCDrawPathsOp> op;
- float conservativeSize = SkTMax(conservativeDevBounds.height(), conservativeDevBounds.width());
- if (conservativeSize > kPathCropThreshold) {
- // The path is too large. Crop it or analytic AA can run out of fp32 precision.
- SkPath croppedDevPath;
- shape.asPath(&croppedDevPath);
- croppedDevPath.transform(m, &croppedDevPath);
-
- SkIRect cropBox = clipIBounds;
- GrShape croppedDevShape;
- if (stroke.isFillStyle()) {
- GrCoverageCountingPathRenderer::CropPath(croppedDevPath, cropBox, &croppedDevPath);
- croppedDevShape = GrShape(croppedDevPath);
- conservativeDevBounds = croppedDevShape.bounds();
- } else {
- int r = SkScalarCeilToInt(conservativeInflationRadius);
- cropBox.outset(r, r);
- GrCoverageCountingPathRenderer::CropPath(croppedDevPath, cropBox, &croppedDevPath);
- SkStrokeRec devStroke = stroke;
- devStroke.setStrokeStyle(strokeDevWidth);
- croppedDevShape = GrShape(croppedDevPath, GrStyle(devStroke, nullptr));
- conservativeDevBounds = croppedDevPath.getBounds();
- conservativeDevBounds.outset(conservativeInflationRadius, conservativeInflationRadius);
- }
-
- // FIXME: This breaks local coords: http://skbug.com/8003
- return InternalMake(context, clipIBounds, SkMatrix::I(), croppedDevShape, strokeDevWidth,
- conservativeDevBounds, std::move(paint));
- }
-
- return InternalMake(context, clipIBounds, m, shape, strokeDevWidth, conservativeDevBounds,
- std::move(paint));
-}
-
-std::unique_ptr<GrCCDrawPathsOp> GrCCDrawPathsOp::InternalMake(
- GrContext* context, const SkIRect& clipIBounds, const SkMatrix& m, const GrShape& shape,
- float strokeDevWidth, const SkRect& conservativeDevBounds, GrPaint&& paint) {
- SkIRect shapeConservativeIBounds;
- conservativeDevBounds.roundOut(&shapeConservativeIBounds);
+std::unique_ptr<GrCCDrawPathsOp> GrCCDrawPathsOp::Make(GrContext* context,
+ const SkIRect& clipIBounds,
+ const SkMatrix& m,
+ const GrShape& shape,
+ const SkRect& devBounds,
+ GrPaint&& paint) {
+ SkIRect shapeDevIBounds;
+ devBounds.roundOut(&shapeDevIBounds); // GrCCPathParser might find slightly tighter bounds.
SkIRect maskDevIBounds;
Visibility maskVisibility;
- if (clipIBounds.contains(shapeConservativeIBounds)) {
- maskDevIBounds = shapeConservativeIBounds;
+ if (clipIBounds.contains(shapeDevIBounds)) {
+ maskDevIBounds = shapeDevIBounds;
maskVisibility = Visibility::kComplete;
} else {
- if (!maskDevIBounds.intersect(clipIBounds, shapeConservativeIBounds)) {
+ if (!maskDevIBounds.intersect(clipIBounds, shapeDevIBounds)) {
return nullptr;
}
- int64_t unclippedArea = area(shapeConservativeIBounds);
+ int64_t unclippedArea = area(shapeDevIBounds);
int64_t clippedArea = area(maskDevIBounds);
maskVisibility = (clippedArea >= unclippedArea/2 || unclippedArea < 100*100)
? Visibility::kMostlyComplete // i.e., visible enough to justify rendering the
@@ -113,24 +56,22 @@
GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
- return pool->allocate<GrCCDrawPathsOp>(m, shape, strokeDevWidth, shapeConservativeIBounds,
- maskDevIBounds, maskVisibility, conservativeDevBounds,
- std::move(paint));
+ return pool->allocate<GrCCDrawPathsOp>(m, shape, shapeDevIBounds, maskDevIBounds,
+ maskVisibility, devBounds, std::move(paint));
}
-GrCCDrawPathsOp::GrCCDrawPathsOp(const SkMatrix& m, const GrShape& shape, float strokeDevWidth,
- const SkIRect& shapeConservativeIBounds,
- const SkIRect& maskDevIBounds, Visibility maskVisibility,
- const SkRect& conservativeDevBounds, GrPaint&& paint)
+GrCCDrawPathsOp::GrCCDrawPathsOp(const SkMatrix& m, const GrShape& shape,
+ const SkIRect& shapeDevIBounds, const SkIRect& maskDevIBounds,
+ Visibility maskVisibility, const SkRect& devBounds,
+ GrPaint&& paint)
: GrDrawOp(ClassID())
, fViewMatrixIfUsingLocalCoords(has_coord_transforms(paint) ? m : SkMatrix::I())
- , fDraws(m, shape, strokeDevWidth, shapeConservativeIBounds, maskDevIBounds, maskVisibility,
- paint.getColor())
+ , fDraws(m, shape, shapeDevIBounds, maskDevIBounds, maskVisibility, paint.getColor())
, fProcessors(std::move(paint)) { // Paint must be moved after fetching its color above.
SkDEBUGCODE(fBaseInstance = -1);
// FIXME: intersect with clip bounds to (hopefully) improve batching.
// (This is nontrivial due to assumptions in generating the octagon cover geometry.)
- this->setBounds(conservativeDevBounds, GrOp::HasAABloat::kYes, GrOp::IsZeroArea::kNo);
+ this->setBounds(devBounds, GrOp::HasAABloat::kYes, GrOp::IsZeroArea::kNo);
}
GrCCDrawPathsOp::~GrCCDrawPathsOp() {
@@ -141,14 +82,12 @@
}
GrCCDrawPathsOp::SingleDraw::SingleDraw(const SkMatrix& m, const GrShape& shape,
- float strokeDevWidth,
- const SkIRect& shapeConservativeIBounds,
+ const SkIRect& shapeDevIBounds,
const SkIRect& maskDevIBounds, Visibility maskVisibility,
GrColor color)
: fMatrix(m)
, fShape(shape)
- , fStrokeDevWidth(strokeDevWidth)
- , fShapeConservativeIBounds(shapeConservativeIBounds)
+ , fShapeDevIBounds(shapeDevIBounds)
, fMaskDevIBounds(maskDevIBounds)
, fMaskVisibility(maskVisibility)
, fColor(color) {
@@ -172,39 +111,9 @@
GrDrawOp::RequiresDstTexture GrCCDrawPathsOp::finalize(const GrCaps& caps,
const GrAppliedClip* clip) {
SkASSERT(1 == fNumDraws); // There should only be one single path draw in this Op right now.
- SingleDraw* draw = &fDraws.head();
-
- const GrProcessorSet::Analysis& analysis = fProcessors.finalize(
- draw->fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip, false, caps,
- &draw->fColor);
-
- // Lines start looking jagged when they get thinner than 1px. For thin strokes it looks better
- // if we can convert them to hairline (i.e., inflate the stroke width to 1px), and instead
- // reduce the opacity to create the illusion of thin-ness. This strategy also helps reduce
- // artifacts from coverage dilation when there are self intersections.
- if (analysis.isCompatibleWithCoverageAsAlpha() &&
- !draw->fShape.style().strokeRec().isFillStyle() && draw->fStrokeDevWidth < 1) {
- // Modifying the shape affects its cache key. The draw can't have a cache entry yet or else
- // our next step would invalidate it.
- SkASSERT(!draw->fCacheEntry);
- SkASSERT(SkStrokeRec::kStroke_Style == draw->fShape.style().strokeRec().getStyle());
-
- SkPath path;
- draw->fShape.asPath(&path);
-
- // Create a hairline version of our stroke.
- SkStrokeRec hairlineStroke = draw->fShape.style().strokeRec();
- hairlineStroke.setStrokeStyle(0);
-
- // How transparent does a 1px stroke have to be in order to appear as thin as the real one?
- GrColor coverageAsAlpha = GrColorPackA4(SkScalarFloorToInt(draw->fStrokeDevWidth * 255));
-
- draw->fShape = GrShape(path, GrStyle(hairlineStroke, nullptr));
- draw->fStrokeDevWidth = 1;
- // fShapeConservativeIBounds already accounted for this possibility of inflating the stroke.
- draw->fColor = GrColorMul(draw->fColor, coverageAsAlpha);
- }
-
+ GrProcessorSet::Analysis analysis =
+ fProcessors.finalize(fDraws.head().fColor, GrProcessorAnalysisCoverage::kSingleChannel,
+ clip, false, caps, &fDraws.head().fColor);
return RequiresDstTexture(analysis.requiresDstTexture());
}
@@ -271,11 +180,8 @@
// can copy it into a new 8-bit atlas and keep it in the resource cache.
if (stashedAtlasKey.isValid() && stashedAtlasKey == cacheEntry->atlasKey()) {
SkASSERT(!cacheEntry->hasCachedAtlas());
- int idx = (draw.fShape.style().strokeRec().isFillStyle())
- ? GrCCPerFlushResourceSpecs::kFillIdx
- : GrCCPerFlushResourceSpecs::kStrokeIdx;
- ++specs->fNumCopiedPaths[idx];
- specs->fCopyPathStats[idx].statPath(path);
+ ++specs->fNumCopiedPaths;
+ specs->fCopyPathStats.statPath(path);
specs->fCopyAtlasSpecs.accountForSpace(cacheEntry->width(),
cacheEntry->height());
continue;
@@ -285,23 +191,18 @@
cacheEntry->resetAtlasKeyAndInfo();
}
- if (Visibility::kMostlyComplete == draw.fMaskVisibility && cacheEntry->hitCount() > 1) {
- int shapeSize = SkTMax(draw.fShapeConservativeIBounds.height(),
- draw.fShapeConservativeIBounds.width());
- if (shapeSize <= onFlushRP->caps()->maxRenderTargetSize()) {
- // We've seen this path before with a compatible matrix, and it's mostly
- // visible. Just render the whole mask so we can try to cache it.
- draw.fMaskDevIBounds = draw.fShapeConservativeIBounds;
- draw.fMaskVisibility = Visibility::kComplete;
- }
+ if (Visibility::kMostlyComplete == draw.fMaskVisibility && cacheEntry->hitCount() > 1 &&
+ SkTMax(draw.fShapeDevIBounds.height(),
+ draw.fShapeDevIBounds.width()) <= onFlushRP->caps()->maxRenderTargetSize()) {
+ // We've seen this path before with a compatible matrix, and it's mostly visible.
+ // Just render the whole mask so we can try to cache it.
+ draw.fMaskDevIBounds = draw.fShapeDevIBounds;
+ draw.fMaskVisibility = Visibility::kComplete;
}
}
- int idx = (draw.fShape.style().strokeRec().isFillStyle())
- ? GrCCPerFlushResourceSpecs::kFillIdx
- : GrCCPerFlushResourceSpecs::kStrokeIdx;
- ++specs->fNumRenderedPaths[idx];
- specs->fRenderedPathStats[idx].statPath(path);
+ ++specs->fNumRenderedPaths;
+ specs->fRenderedPathStats.statPath(path);
specs->fRenderedAtlasSpecs.accountForSpace(draw.fMaskDevIBounds.width(),
draw.fMaskDevIBounds.height());
}
@@ -318,8 +219,7 @@
SkPath path;
draw.fShape.asPath(&path);
- auto doEvenOddFill = DoEvenOddFill(draw.fShape.style().strokeRec().isFillStyle() &&
- SkPath::kEvenOdd_FillType == path.getFillType());
+ auto doEvenOddFill = DoEvenOddFill(SkPath::kEvenOdd_FillType == path.getFillType());
SkASSERT(SkPath::kEvenOdd_FillType == path.getFillType() ||
SkPath::kWinding_FillType == path.getFillType());
@@ -370,9 +270,9 @@
SkRect devBounds, devBounds45;
SkIRect devIBounds;
SkIVector devToAtlasOffset;
- if (auto atlas = resources->renderShapeInAtlas(
- draw.fMaskDevIBounds, draw.fMatrix, draw.fShape, draw.fStrokeDevWidth,
- &devBounds, &devBounds45, &devIBounds, &devToAtlasOffset)) {
+ if (auto atlas = resources->renderPathInAtlas(draw.fMaskDevIBounds, draw.fMatrix, path,
+ &devBounds, &devBounds45, &devIBounds,
+ &devToAtlasOffset)) {
this->recordInstance(atlas->textureProxy(), resources->nextPathInstanceIdx());
resources->appendDrawPathInstance().set(devBounds, devBounds45, devToAtlasOffset,
draw.fColor, doEvenOddFill);