Make simplifyStroke optional on GrStyledShape
For now we simplify every stroke at the beginning of drawShape*, but in the future we will give the tessellator a chance to claim stroked shapes before simplifying the stroke. Bug: chromium:1172543 Change-Id: Ie90c20a1d342661b9006b16ab1fdad3ebe290ba3 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/362798 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
parent
8ca4626a4b
commit
b8ed2bce50
@ -77,6 +77,8 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
using SimplifyStroke = GrStyledShape::SimplifyStroke;
|
||||
|
||||
class AutoCheckFlush {
|
||||
public:
|
||||
AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
|
||||
@ -721,7 +723,7 @@ void GrSurfaceDrawContext::drawRect(const GrClip* clip,
|
||||
}
|
||||
assert_alive(paint);
|
||||
this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
|
||||
GrStyledShape(rect, *style));
|
||||
GrStyledShape(rect, *style, SimplifyStroke::kNo));
|
||||
}
|
||||
|
||||
void GrSurfaceDrawContext::drawQuadSet(const GrClip* clip,
|
||||
@ -1015,7 +1017,7 @@ void GrSurfaceDrawContext::drawRRect(const GrClip* origClip,
|
||||
|
||||
assert_alive(paint);
|
||||
this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
|
||||
GrStyledShape(rrect, style));
|
||||
GrStyledShape(rrect, style, SimplifyStroke::kNo));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -1439,9 +1441,9 @@ void GrSurfaceDrawContext::drawOval(const GrClip* clip,
|
||||
}
|
||||
|
||||
assert_alive(paint);
|
||||
this->drawShapeUsingPathRenderer(
|
||||
clip, std::move(paint), aa, viewMatrix,
|
||||
GrStyledShape(SkRRect::MakeOval(oval), SkPathDirection::kCW, 2, false, style));
|
||||
this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
|
||||
GrStyledShape(SkRRect::MakeOval(oval), SkPathDirection::kCW, 2,
|
||||
false, style, SimplifyStroke::kNo));
|
||||
}
|
||||
|
||||
void GrSurfaceDrawContext::drawArc(const GrClip* clip,
|
||||
@ -1478,9 +1480,9 @@ void GrSurfaceDrawContext::drawArc(const GrClip* clip,
|
||||
}
|
||||
assert_alive(paint);
|
||||
}
|
||||
this->drawShapeUsingPathRenderer(
|
||||
clip, std::move(paint), aa, viewMatrix,
|
||||
GrStyledShape::MakeArc(oval, startAngle, sweepAngle, useCenter, style));
|
||||
this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
|
||||
GrStyledShape::MakeArc(oval, startAngle, sweepAngle, useCenter,
|
||||
style, SimplifyStroke::kNo));
|
||||
}
|
||||
|
||||
void GrSurfaceDrawContext::drawImageLattice(const GrClip* clip,
|
||||
@ -1558,7 +1560,7 @@ void GrSurfaceDrawContext::drawPath(const GrClip* clip,
|
||||
SkDEBUGCODE(this->validate();)
|
||||
GR_CREATE_TRACE_MARKER_CONTEXT("GrSurfaceDrawContext", "drawPath", fContext);
|
||||
|
||||
GrStyledShape shape(path, style);
|
||||
GrStyledShape shape(path, style, SimplifyStroke::kNo);
|
||||
this->drawShape(clip, std::move(paint), aa, viewMatrix, std::move(shape));
|
||||
}
|
||||
|
||||
@ -1581,6 +1583,10 @@ void GrSurfaceDrawContext::drawShape(const GrClip* clip,
|
||||
|
||||
AutoCheckFlush acf(this->drawingManager());
|
||||
|
||||
// Always simplify the stroke for now. In the future we will give the tessellator a chance to
|
||||
// claim strokes before trying to simplify them.
|
||||
shape.simplifyStroke();
|
||||
|
||||
if (!shape.style().hasPathEffect()) {
|
||||
GrAAType aaType = this->chooseAAType(aa);
|
||||
SkPoint linePts[2];
|
||||
@ -1780,6 +1786,10 @@ void GrSurfaceDrawContext::drawShapeUsingPathRenderer(const GrClip* clip,
|
||||
return;
|
||||
}
|
||||
|
||||
// Always simplify the stroke for now. In the future we will give the tessellator a chance to
|
||||
// claim strokes before trying to simplify them.
|
||||
shape.simplifyStroke();
|
||||
|
||||
if (attemptShapeFallback && shape.simplified()) {
|
||||
// Usually we enter drawShapeUsingPathRenderer() because the shape+style was too
|
||||
// complex for dedicated draw ops. However, if GrStyledShape was able to reduce something
|
||||
|
@ -42,7 +42,8 @@ static bool is_inverted(bool originalIsInverted, GrStyledShape::FillInversion in
|
||||
return false;
|
||||
}
|
||||
|
||||
GrStyledShape GrStyledShape::MakeFilled(const GrStyledShape& original, FillInversion inversion) {
|
||||
GrStyledShape GrStyledShape::MakeFilled(const GrStyledShape& original, FillInversion inversion,
|
||||
SimplifyStroke simplifyStroke) {
|
||||
bool newIsInverted = is_inverted(original.fShape.inverted(), inversion);
|
||||
if (original.style().isSimpleFill() && newIsInverted == original.fShape.inverted()) {
|
||||
// By returning the original rather than falling through we can preserve any inherited style
|
||||
@ -63,7 +64,7 @@ GrStyledShape GrStyledShape::MakeFilled(const GrStyledShape& original, FillInver
|
||||
// Going from a non-filled style to fill may allow additional simplifications (e.g.
|
||||
// closing an open rect that wasn't closed in the original shape because it had
|
||||
// stroke style).
|
||||
result.simplify();
|
||||
result.simplify(simplifyStroke);
|
||||
// The above simplify() call only sets simplified to true if its geometry was changed,
|
||||
// since it already sees its style as a simple fill. Since the original style was not a
|
||||
// simple fill, MakeFilled always simplifies.
|
||||
@ -305,11 +306,11 @@ void GrStyledShape::addGenIDChangeListener(sk_sp<SkIDChangeListener> listener) c
|
||||
|
||||
GrStyledShape GrStyledShape::MakeArc(const SkRect& oval, SkScalar startAngleDegrees,
|
||||
SkScalar sweepAngleDegrees, bool useCenter,
|
||||
const GrStyle& style) {
|
||||
const GrStyle& style, SimplifyStroke simplifyStroke) {
|
||||
GrStyledShape result;
|
||||
result.fShape.setArc({oval.makeSorted(), startAngleDegrees, sweepAngleDegrees, useCenter});
|
||||
result.fStyle = style;
|
||||
result.simplify();
|
||||
result.simplify(simplifyStroke);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -416,7 +417,7 @@ GrStyledShape::GrStyledShape(const GrStyledShape& parent, GrStyle::Apply apply,
|
||||
} else if (parent.fShape.isPath() && !parent.fShape.path().isVolatile()) {
|
||||
fInheritedPathForListeners.set(parent.fShape.path());
|
||||
}
|
||||
this->simplify();
|
||||
this->simplify(SimplifyStroke::kYes);
|
||||
this->setInheritedKey(*parentForKey, apply, scale);
|
||||
}
|
||||
|
||||
@ -561,9 +562,25 @@ bool GrStyledShape::asNestedRects(SkRect rects[2]) const {
|
||||
return allEq || allGoE1;
|
||||
}
|
||||
|
||||
void GrStyledShape::simplify() {
|
||||
// Dashing ignores inverseness skbug.com/5421.
|
||||
bool inverted = !fStyle.isDashed() && fShape.inverted();
|
||||
class AutoRestoreInverseness {
|
||||
public:
|
||||
AutoRestoreInverseness(GrShape* shape, const GrStyle& style)
|
||||
// Dashing ignores inverseness skbug.com/5421.
|
||||
: fShape(shape), fInverted(!style.isDashed() && fShape->inverted()) {}
|
||||
|
||||
~AutoRestoreInverseness() {
|
||||
// Restore invertedness after any modifications were made to the shape type
|
||||
fShape->setInverted(fInverted);
|
||||
SkASSERT(!fShape->isPath() || fInverted == fShape->path().isInverseFillType());
|
||||
}
|
||||
|
||||
private:
|
||||
GrShape* fShape;
|
||||
bool fInverted;
|
||||
};
|
||||
|
||||
void GrStyledShape::simplify(SimplifyStroke simplifyStroke) {
|
||||
AutoRestoreInverseness ari(&fShape, fStyle);
|
||||
|
||||
unsigned simplifyFlags = 0;
|
||||
if (fStyle.isSimpleFill()) {
|
||||
@ -579,7 +596,7 @@ void GrStyledShape::simplify() {
|
||||
// Remember if the original shape was closed; in the event we simplify to a point or line
|
||||
// because of degenerate geometry, we need to update joins and caps.
|
||||
GrShape::Type oldType = fShape.type();
|
||||
bool wasClosed = fShape.simplify(simplifyFlags);
|
||||
fClosed = fShape.simplify(simplifyFlags);
|
||||
fSimplified = oldType != fShape.type();
|
||||
|
||||
if (fShape.isPath()) {
|
||||
@ -605,16 +622,16 @@ void GrStyledShape::simplify() {
|
||||
// drawing simple shapes.
|
||||
fInheritedPathForListeners.reset();
|
||||
|
||||
// Further simplifications to the shape based on the style
|
||||
fSimplified |= this->simplifyStroke(wasClosed);
|
||||
if (simplifyStroke == SimplifyStroke::kYes) {
|
||||
// Further simplifications to the shape based on the style
|
||||
this->simplifyStroke();
|
||||
}
|
||||
}
|
||||
|
||||
// Restore invertedness after any modifications were made to the shape type
|
||||
fShape.setInverted(inverted);
|
||||
SkASSERT(!fShape.isPath() || inverted == fShape.path().isInverseFillType());
|
||||
}
|
||||
|
||||
bool GrStyledShape::simplifyStroke(bool originallyClosed) {
|
||||
void GrStyledShape::simplifyStroke() {
|
||||
AutoRestoreInverseness ari(&fShape, fStyle);
|
||||
|
||||
// For stroke+filled rects, a mitered shape becomes a larger rect and a rounded shape
|
||||
// becomes a round rect.
|
||||
if (!fStyle.hasPathEffect() && fShape.isRect() &&
|
||||
@ -623,7 +640,7 @@ bool GrStyledShape::simplifyStroke(bool originallyClosed) {
|
||||
(fStyle.strokeRec().getJoin() == SkPaint::kMiter_Join &&
|
||||
fStyle.strokeRec().getMiter() < SK_ScalarSqrt2)) {
|
||||
// Bevel-stroked rect needs path rendering
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
SkScalar r = fStyle.strokeRec().getWidth() / 2;
|
||||
@ -634,14 +651,15 @@ bool GrStyledShape::simplifyStroke(bool originallyClosed) {
|
||||
fShape.setRRect(SkRRect::MakeRectXY(fShape.rect(), r, r));
|
||||
}
|
||||
fStyle = GrStyle::SimpleFill();
|
||||
return true;
|
||||
fSimplified = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, if we're a point or a line, we might be able to explicitly apply some of the
|
||||
// stroking (and even some of the dashing). Any other shape+style is too complicated to reduce.
|
||||
if ((!fShape.isPoint() && !fShape.isLine()) || fStyle.hasNonDashPathEffect() ||
|
||||
fStyle.strokeRec().isHairlineStyle()) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Tracks style simplifications, even if the geometry can't be further simplified.
|
||||
@ -665,13 +683,13 @@ bool GrStyledShape::simplifyStroke(bool originallyClosed) {
|
||||
}
|
||||
|
||||
if (!dropDash) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
// Fall through to modifying the shape to respect the new stroke geometry
|
||||
fStyle = GrStyle(fStyle.strokeRec(), nullptr);
|
||||
// Since the reduced the line or point after dashing is dependent on the caps of the dashes,
|
||||
// we reset to be unclosed so we don't override the style based on joins later.
|
||||
originallyClosed = false;
|
||||
fClosed = false;
|
||||
styleSimplified = true;
|
||||
}
|
||||
|
||||
@ -680,7 +698,8 @@ bool GrStyledShape::simplifyStroke(bool originallyClosed) {
|
||||
bool strokeAndFilled = false;
|
||||
if (fStyle.isSimpleFill()) {
|
||||
fShape.reset();
|
||||
return true;
|
||||
fSimplified = true;
|
||||
return;
|
||||
} else if (fStyle.strokeRec().getStyle() == SkStrokeRec::kStrokeAndFill_Style) {
|
||||
// Stroke only
|
||||
SkStrokeRec rec = fStyle.strokeRec();
|
||||
@ -692,7 +711,7 @@ bool GrStyledShape::simplifyStroke(bool originallyClosed) {
|
||||
|
||||
// A point or line that was formed by a degenerate closed shape needs its style updated to
|
||||
// reflect the fact that it doesn't actually produce caps.
|
||||
if (originallyClosed) {
|
||||
if (fClosed) {
|
||||
SkPaint::Cap cap;
|
||||
if (fShape.isLine() && fStyle.strokeRec().getJoin() == SkPaint::kRound_Join) {
|
||||
// As a closed shape, the line moves from a to b and back to a, producing a 180 degree
|
||||
@ -761,7 +780,8 @@ bool GrStyledShape::simplifyStroke(bool originallyClosed) {
|
||||
} else {
|
||||
// Geometrically can't apply the style and turn into a fill, but might still be simpler
|
||||
// than before based solely on changes to fStyle.
|
||||
return styleSimplified;
|
||||
fSimplified |= styleSimplified;
|
||||
return;
|
||||
}
|
||||
rect.outset(outset.fX, outset.fY);
|
||||
if (rect.isEmpty()) {
|
||||
@ -775,5 +795,6 @@ bool GrStyledShape::simplifyStroke(bool originallyClosed) {
|
||||
}
|
||||
// If we made it here, the stroke was fully applied to the new shape so we can become a fill.
|
||||
fStyle = GrStyle::SimpleFill();
|
||||
return true;
|
||||
fSimplified = true;
|
||||
return;
|
||||
}
|
||||
|
@ -44,44 +44,61 @@ public:
|
||||
|
||||
GrStyledShape() {}
|
||||
|
||||
explicit GrStyledShape(const SkPath& path) : GrStyledShape(path, GrStyle::SimpleFill()) {}
|
||||
enum class SimplifyStroke : bool { kNo = false, kYes };
|
||||
|
||||
explicit GrStyledShape(const SkRRect& rrect) : GrStyledShape(rrect, GrStyle::SimpleFill()) {}
|
||||
explicit GrStyledShape(const SkPath& path)
|
||||
: GrStyledShape(path, GrStyle::SimpleFill(), SimplifyStroke::kNo) {}
|
||||
|
||||
explicit GrStyledShape(const SkRect& rect) : GrStyledShape(rect, GrStyle::SimpleFill()) {}
|
||||
explicit GrStyledShape(const SkRRect& rrect)
|
||||
: GrStyledShape(rrect, GrStyle::SimpleFill(), SimplifyStroke::kNo) {}
|
||||
|
||||
GrStyledShape(const SkPath& path, const SkPaint& paint) : GrStyledShape(path, GrStyle(paint)) {}
|
||||
explicit GrStyledShape(const SkRect& rect)
|
||||
: GrStyledShape(rect, GrStyle::SimpleFill(), SimplifyStroke::kNo) {}
|
||||
|
||||
GrStyledShape(const SkRRect& rrect, const SkPaint& paint)
|
||||
: GrStyledShape(rrect, GrStyle(paint)) {}
|
||||
GrStyledShape(const SkPath& path, const SkPaint& paint,
|
||||
SimplifyStroke simplifyStroke = SimplifyStroke::kYes)
|
||||
: GrStyledShape(path, GrStyle(paint), simplifyStroke) {}
|
||||
|
||||
GrStyledShape(const SkRect& rect, const SkPaint& paint) : GrStyledShape(rect, GrStyle(paint)) {}
|
||||
GrStyledShape(const SkRRect& rrect, const SkPaint& paint,
|
||||
SimplifyStroke simplifyStroke = SimplifyStroke::kYes)
|
||||
: GrStyledShape(rrect, GrStyle(paint), simplifyStroke) {}
|
||||
|
||||
GrStyledShape(const SkPath& path, const GrStyle& style) : fShape(path), fStyle(style) {
|
||||
this->simplify();
|
||||
GrStyledShape(const SkRect& rect, const SkPaint& paint,
|
||||
SimplifyStroke simplifyStroke = SimplifyStroke::kYes)
|
||||
: GrStyledShape(rect, GrStyle(paint), simplifyStroke) {}
|
||||
|
||||
GrStyledShape(const SkPath& path, const GrStyle& style,
|
||||
SimplifyStroke simplifyStroke = SimplifyStroke::kYes)
|
||||
: fShape(path), fStyle(style) {
|
||||
this->simplify(simplifyStroke);
|
||||
}
|
||||
|
||||
GrStyledShape(const SkRRect& rrect, const GrStyle& style) : fShape(rrect), fStyle(style) {
|
||||
this->simplify();
|
||||
GrStyledShape(const SkRRect& rrect, const GrStyle& style,
|
||||
SimplifyStroke simplifyStroke = SimplifyStroke::kYes)
|
||||
: fShape(rrect), fStyle(style) {
|
||||
this->simplify(simplifyStroke);
|
||||
}
|
||||
|
||||
GrStyledShape(const SkRRect& rrect, SkPathDirection dir, unsigned start, bool inverted,
|
||||
const GrStyle& style)
|
||||
const GrStyle& style, SimplifyStroke simplifyStroke = SimplifyStroke::kYes)
|
||||
: fShape(rrect)
|
||||
, fStyle(style) {
|
||||
fShape.setPathWindingParams(dir, start);
|
||||
fShape.setInverted(inverted);
|
||||
this->simplify();
|
||||
this->simplify(simplifyStroke);
|
||||
}
|
||||
|
||||
GrStyledShape(const SkRect& rect, const GrStyle& style) : fShape(rect), fStyle(style) {
|
||||
this->simplify();
|
||||
GrStyledShape(const SkRect& rect, const GrStyle& style,
|
||||
SimplifyStroke simplifyStroke = SimplifyStroke::kYes)
|
||||
: fShape(rect), fStyle(style) {
|
||||
this->simplify(simplifyStroke);
|
||||
}
|
||||
|
||||
GrStyledShape(const GrStyledShape&);
|
||||
|
||||
static GrStyledShape MakeArc(const SkRect& oval, SkScalar startAngleDegrees,
|
||||
SkScalar sweepAngleDegrees, bool useCenter, const GrStyle& style);
|
||||
SkScalar sweepAngleDegrees, bool useCenter, const GrStyle& style,
|
||||
SimplifyStroke = SimplifyStroke::kYes);
|
||||
|
||||
GrStyledShape& operator=(const GrStyledShape& that);
|
||||
|
||||
@ -103,7 +120,8 @@ public:
|
||||
* made non-inverted since dashing ignores inverseness).
|
||||
*/
|
||||
static GrStyledShape MakeFilled(const GrStyledShape& original,
|
||||
FillInversion = FillInversion::kPreserve);
|
||||
FillInversion = FillInversion::kPreserve,
|
||||
SimplifyStroke = SimplifyStroke::kYes);
|
||||
|
||||
const GrStyle& style() const { return fStyle; }
|
||||
|
||||
@ -249,6 +267,12 @@ public:
|
||||
bool testingOnly_isPath() const;
|
||||
bool testingOnly_isNonVolatilePath() const;
|
||||
|
||||
/**
|
||||
* As an optional part of the simplification process, some shapes can have stroking trivially
|
||||
* evaluated and form a new geometry with just a fill.
|
||||
*/
|
||||
void simplifyStroke();
|
||||
|
||||
private:
|
||||
/** Constructor used by the applyStyle() function */
|
||||
GrStyledShape(const GrStyledShape& parentShape, GrStyle::Apply, SkScalar scale);
|
||||
@ -259,12 +283,12 @@ private:
|
||||
*/
|
||||
void setInheritedKey(const GrStyledShape& parentShape, GrStyle::Apply, SkScalar scale);
|
||||
|
||||
// Similar to GrShape::simplify but also takes into account style and stroking, possibly
|
||||
// applying the style explicitly to produce a new analytic shape with a simpler style.
|
||||
void simplify();
|
||||
// As part of the simplification process, some shapes can have stroking trivially evaluated
|
||||
// and form a new geometry with just a fill.
|
||||
bool simplifyStroke(bool originallyClosed);
|
||||
/**
|
||||
* Similar to GrShape::simplify but also takes into account style and, optionally, stroking.
|
||||
* Some stroked shapes can be represented as a different filled primitive (e.g. a stroked line
|
||||
* becomes a filled round rect). When SimplifyStroke is kYes, such optimizations are permitted.
|
||||
*/
|
||||
void simplify(SimplifyStroke);
|
||||
|
||||
/** Gets the path that gen id listeners should be added to. */
|
||||
const SkPath* originalPathForListeners() const;
|
||||
@ -273,6 +297,7 @@ private:
|
||||
GrStyle fStyle;
|
||||
// Gen ID of the original path (path may be modified or simplified away).
|
||||
int32_t fGenID = 0;
|
||||
bool fClosed = false;
|
||||
bool fSimplified = false;
|
||||
|
||||
SkTLazy<SkPath> fInheritedPathForListeners;
|
||||
|
Loading…
Reference in New Issue
Block a user