diff options
author | caryclark <caryclark@google.com> | 2016-08-25 05:21:14 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-08-25 05:21:14 -0700 |
commit | 025b11ecde8733d9b3eee54e132cc50a5ce8eb78 (patch) | |
tree | 1f6f2353f17028e66b2f64e7914f527a880f721b /src/pathops/SkPathOpsDebug.cpp | |
parent | b8b3f71c5589aaed8ae76727f3d62642a192b359 (diff) |
add pathops debugging
Pathops has many points of failure, most of which
are triggered by extreme data generated by fuzzers.
It's difficult to figure out which failure point
was triggered when the operation gives up.
Add instrumentation so that the failure can
be debugged when the data is well-behaved.
Also, add a check that looks for a sequence of
coincident points on multiple edges that are out
of order when compared to each other.
TBR=reed@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2274803003
Review-Url: https://codereview.chromium.org/2274803003
Diffstat (limited to 'src/pathops/SkPathOpsDebug.cpp')
-rw-r--r-- | src/pathops/SkPathOpsDebug.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/pathops/SkPathOpsDebug.cpp b/src/pathops/SkPathOpsDebug.cpp index 4d833a0b84..df35be0cfe 100644 --- a/src/pathops/SkPathOpsDebug.cpp +++ b/src/pathops/SkPathOpsDebug.cpp @@ -975,6 +975,26 @@ void SkOpSegment::debugReset() { this->init(this->fPts, this->fWeight, this->contour(), this->verb()); } +#if DEBUG_COINCIDENCE_ORDER +void SkOpSegment::debugSetCoinT(int index, SkScalar t) const { + if (fDebugBaseMax < 0 || fDebugBaseIndex == index) { + fDebugBaseIndex = index; + fDebugBaseMin = SkTMin(t, fDebugBaseMin); + fDebugBaseMax = SkTMax(t, fDebugBaseMax); + return; + } + SkASSERT(fDebugBaseMin >= t || t >= fDebugBaseMax); + if (fDebugLastMax < 0 || fDebugLastIndex == index) { + fDebugLastIndex = index; + fDebugLastMin = SkTMin(t, fDebugLastMin); + fDebugLastMax = SkTMax(t, fDebugLastMax); + return; + } + SkASSERT(fDebugLastMin >= t || t >= fDebugLastMax); + SkASSERT((t - fDebugBaseMin > 0) == (fDebugLastMin - fDebugBaseMin > 0)); +} +#endif + #if DEBUG_ACTIVE_SPANS void SkOpSegment::debugShowActiveSpans() const { debugValidate(); @@ -1290,6 +1310,7 @@ bool SkCoincidentSpans::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* l return expanded; } +#undef FAIL_IF #define FAIL_IF(cond) do { if (cond) log->record(kAddExpandedFail_Glitch, id, coin); } while (false) /* Commented-out lines keep this in sync with addExpanded */ @@ -1976,7 +1997,31 @@ void SkOpContour::debugMissingCoincidence(const char* id, SkPathOpsDebug::Glitch } #endif +#if DEBUG_COINCIDENCE_ORDER +void SkOpSegment::debugResetCoinT() const { + fDebugBaseIndex = -1; + fDebugBaseMin = 1; + fDebugBaseMax = -1; + fDebugLastIndex = -1; + fDebugLastMin = 1; + fDebugLastMax = -1; +} +#endif + void SkOpSegment::debugValidate() const { +#if DEBUG_COINCIDENCE_ORDER + { + const SkOpSpanBase* span = &fHead; + do { + span->debugResetCoinT(); + } while (!span->final() && (span = span->upCast()->next())); + span = &fHead; + int index = 0; + do { + span->debugSetCoinT(index++); + } while (!span->final() && (span = span->upCast()->next())); + } +#endif #if DEBUG_COINCIDENCE if (this->globalState()->debugCheckHealth()) { return; @@ -2127,6 +2172,28 @@ void SkOpSpanBase::debugMergeContained(const char* id, SkPathOpsDebug::GlitchLog } #endif +void SkOpSpanBase::debugResetCoinT() const { +#if DEBUG_COINCIDENCE_ORDER + const SkOpPtT* ptT = &fPtT; + do { + ptT->debugResetCoinT(); + ptT = ptT->next(); + } while (ptT != &fPtT); +#endif +} + +void SkOpSpanBase::debugSetCoinT(int index) const { +#if DEBUG_COINCIDENCE_ORDER + const SkOpPtT* ptT = &fPtT; + do { + if (!ptT->deleted()) { + ptT->debugSetCoinT(index); + } + ptT = ptT->next(); + } while (ptT != &fPtT); +#endif +} + const SkOpSpan* SkOpSpanBase::debugStarter(SkOpSpanBase const** endPtr) const { const SkOpSpanBase* end = *endPtr; SkASSERT(this->segment() == end->segment()); @@ -2336,6 +2403,18 @@ int SkOpPtT::debugLoopLimit(bool report) const { return 0; } +void SkOpPtT::debugResetCoinT() const { +#if DEBUG_COINCIDENCE_ORDER + this->segment()->debugResetCoinT(); +#endif +} + +void SkOpPtT::debugSetCoinT(int index) const { +#if DEBUG_COINCIDENCE_ORDER + this->segment()->debugSetCoinT(index, fT); +#endif +} + void SkOpPtT::debugValidate() const { #if DEBUG_COINCIDENCE if (this->globalState()->debugCheckHealth()) { |