Update ShouldUseAAA with our better complexity estimation
See https://groups.google.com/forum/#!topic/skia-discuss/QrJadRQR5A4 for the issue. Bug: skia: Change-Id: I260d1a57f64ff7a2fc47e6bce00cd8b8dbca81a9 Reviewed-on: https://skia-review.googlesource.com/144412 Reviewed-by: Cary Clark <caryclark@google.com> Commit-Queue: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
790926ac3a
commit
e847af7e0d
@ -599,30 +599,21 @@ static SkIRect safeRoundOut(const SkRect& src) {
|
||||
return dst;
|
||||
}
|
||||
|
||||
static bool ShouldUseDAA(const SkPath& path) {
|
||||
if (gSkForceDeltaAA) {
|
||||
return true;
|
||||
}
|
||||
if (!gSkUseDeltaAA || SkPathPriv::IsBadForDAA(path)) {
|
||||
return false;
|
||||
}
|
||||
constexpr int kSampleSize = 8;
|
||||
constexpr SkScalar kComplexityThreshold = 0.25;
|
||||
constexpr SkScalar kSmallCubicThreshold = 16;
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_AA_CHOICE
|
||||
const SkRect& bounds = path.getBounds();
|
||||
return !path.isConvex() && path.countPoints() >= SkTMax(bounds.width(), bounds.height()) / 8;
|
||||
#else
|
||||
constexpr int kSampleSize = 8;
|
||||
constexpr SkScalar kComplexityThreshold = 0.25;
|
||||
constexpr SkScalar kSmallCubicThreshold = 16;
|
||||
static inline SkScalar sqr(SkScalar x) {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
static void ComputeComplexity(const SkPath& path, SkScalar& avgLength, SkScalar& complexity) {
|
||||
int n = path.countPoints();
|
||||
if (path.isConvex() || n < kSampleSize || path.getBounds().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// DAA is fast with mask
|
||||
if (SkCoverageDeltaMask::CanHandle(safeRoundOut(path.getBounds()))) {
|
||||
return true;
|
||||
if (n < kSampleSize) {
|
||||
// set to invalid value to indicate that we failed to compute
|
||||
avgLength = -1;
|
||||
complexity = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
SkScalar sumLength = 0;
|
||||
@ -632,7 +623,34 @@ static bool ShouldUseDAA(const SkPath& path) {
|
||||
sumLength += SkPoint::Distance(lastPoint, point);
|
||||
lastPoint = point;
|
||||
}
|
||||
SkScalar avgLength = sumLength / (kSampleSize - 1);
|
||||
avgLength = sumLength / (kSampleSize - 1);
|
||||
|
||||
SkScalar diagonalSqr = sqr(path.getBounds().width()) + sqr(path.getBounds().height());
|
||||
|
||||
// If the path consists of random line segments, the number of intersections should be
|
||||
// proportional to this.
|
||||
SkScalar intersections = sqr(n) * sqr(avgLength) / diagonalSqr;
|
||||
|
||||
// The number of intersections per scanline should be proportional to this number.
|
||||
complexity = intersections / path.getBounds().height();
|
||||
}
|
||||
|
||||
static bool ShouldUseDAA(const SkPath& path, SkScalar avgLength, SkScalar complexity) {
|
||||
if (gSkForceDeltaAA) {
|
||||
return true;
|
||||
}
|
||||
if (!gSkUseDeltaAA || SkPathPriv::IsBadForDAA(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (avgLength < 0 || complexity < 0 || path.getBounds().isEmpty() || path.isConvex()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// DAA is fast with mask
|
||||
if (SkCoverageDeltaMask::CanHandle(safeRoundOut(path.getBounds()))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// DAA is much faster in small cubics (since we don't have to chop them).
|
||||
// If there are many cubics, and the average length if small, use DAA.
|
||||
@ -648,25 +666,10 @@ static bool ShouldUseDAA(const SkPath& path) {
|
||||
}
|
||||
}
|
||||
|
||||
SkScalar diagonal = SkPoint::Length(path.getBounds().width(), path.getBounds().height());
|
||||
|
||||
// On average, what's the distance between two consecutive points; the number is normalized
|
||||
// to a range of [0, 1] where 1 corresponds to the maximum length of the diagonal.
|
||||
SkScalar sampleSpan = avgLength / diagonal;
|
||||
|
||||
|
||||
// If the path is consist of random line segments, the number of intersections should be
|
||||
// proportional to (n * sampleSpan)^2
|
||||
SkScalar intersections = (n * sampleSpan) * (n * sampleSpan);
|
||||
|
||||
// The number of intersections per scanline should be proportional to this number.
|
||||
SkScalar complexity = intersections / path.getBounds().height();
|
||||
|
||||
return complexity >= kComplexityThreshold;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool ShouldUseAAA(const SkPath& path) {
|
||||
static bool ShouldUseAAA(const SkPath& path, SkScalar avgLength, SkScalar complexity) {
|
||||
if (gSkForceAnalyticAA) {
|
||||
return true;
|
||||
}
|
||||
@ -676,6 +679,8 @@ static bool ShouldUseAAA(const SkPath& path) {
|
||||
if (path.isRect(nullptr)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_AAA_CHOICE
|
||||
const SkRect& bounds = path.getBounds();
|
||||
// When the path have so many points compared to the size of its bounds/resolution,
|
||||
// it indicates that the path is not quite smooth in the current resolution:
|
||||
@ -683,6 +688,10 @@ static bool ShouldUseAAA(const SkPath& path) {
|
||||
// zero. Hence Aanlytic AA is not likely to produce visible quality improvements, and Analytic
|
||||
// AA might be slower than supersampling.
|
||||
return path.countPoints() < SkTMax(bounds.width(), bounds.height()) / 2 - 10;
|
||||
#else
|
||||
// We will use AAA if the number of verbs < kSampleSize and therefore complexity < 0
|
||||
return complexity < kComplexityThreshold;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SkScan::SAAFillPath(const SkPath& path, SkBlitter* blitter, const SkIRect& ir,
|
||||
@ -800,9 +809,12 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
|
||||
sk_blit_above(blitter, ir, *clipRgn);
|
||||
}
|
||||
|
||||
if (daaRecord || ShouldUseDAA(path)) {
|
||||
SkScalar avgLength, complexity;
|
||||
ComputeComplexity(path, avgLength, complexity);
|
||||
|
||||
if (daaRecord || ShouldUseDAA(path, avgLength, complexity)) {
|
||||
SkScan::DAAFillPath(path, blitter, ir, clipRgn->getBounds(), forceRLE, daaRecord);
|
||||
} else if (ShouldUseAAA(path)) {
|
||||
} else if (ShouldUseAAA(path, avgLength, complexity)) {
|
||||
// Do not use AAA if path is too complicated:
|
||||
// there won't be any speedup or significant visual improvement.
|
||||
SkScan::AAAFillPath(path, blitter, ir, clipRgn->getBounds(), forceRLE);
|
||||
|
Loading…
Reference in New Issue
Block a user