Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Unified Diff: src/pathops/SkPathOpsDebug.cpp

Issue 2441763003: formalize host debugging (Closed)
Patch Set: merge with ToT Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/pathops/SkPathOpsDebug.h ('k') | src/pathops/SkPathOpsOp.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pathops/SkPathOpsDebug.cpp
diff --git a/src/pathops/SkPathOpsDebug.cpp b/src/pathops/SkPathOpsDebug.cpp
index 476fafb4258ba2279c8efd72a208bd85cd6b414d..58b33c0ab9cddbe7fadb35241333390801dd946e 100644
--- a/src/pathops/SkPathOpsDebug.cpp
+++ b/src/pathops/SkPathOpsDebug.cpp
@@ -8,10 +8,19 @@
#include "SkMutex.h"
#include "SkOpCoincidence.h"
#include "SkOpContour.h"
+#include "SkOSFile.h"
#include "SkPath.h"
#include "SkPathOpsDebug.h"
#include "SkString.h"
+#ifdef SK_DEBUG
+bool SkPathOpsDebug::gDumpOp; // set to true to write op to file before a crash
+bool SkPathOpsDebug::gVerifyOp; // set to true to compare result against regions
+#endif
+
+bool SkPathOpsDebug::gRunFail; // set to true to check for success on tests known to fail
+bool SkPathOpsDebug::gVeryVerbose; // set to true to run extensive checking tests
+
#undef FAIL_IF
#define FAIL_IF(cond, coin) \
do { if (cond) log->record(SkPathOpsDebug::kFail_Glitch, coin); } while (false)
@@ -27,10 +36,6 @@
class SkCoincidentSpans;
-#if DEBUG_VALIDATE
-extern bool FLAGS_runFail;
-#endif
-
#if DEBUG_SORT
int SkPathOpsDebug::gSortCountDefault = SK_MaxS32;
int SkPathOpsDebug::gSortCount;
@@ -647,15 +652,9 @@ void SkOpGlobalState::debugResetLoopCounts() {
}
#endif
-#ifdef SK_DEBUG
-bool SkOpGlobalState::debugRunFail() const {
-#if DEBUG_VALIDATE
- return FLAGS_runFail;
-#else
- return false;
-#endif
+bool SkOpGlobalState::DebugRunFail() {
+ return SkPathOpsDebug::gRunFail;
}
-#endif
// this is const so it can be called by const methods that overwise don't alter state
#if DEBUG_VALIDATE || DEBUG_COIN
@@ -1362,8 +1361,8 @@ void SkOpAngle::debugValidate() const {
}
next = next->fNext;
} while (next && next != first);
- SkASSERT(wind == 0 || !FLAGS_runFail);
- SkASSERT(opp == 0 || !FLAGS_runFail);
+ SkASSERT(wind == 0 || !SkPathOpsDebug::gRunFail);
+ SkASSERT(opp == 0 || !SkPathOpsDebug::gRunFail);
#endif
}
@@ -1390,8 +1389,8 @@ void SkOpAngle::debugValidateNext() const {
#ifdef SK_DEBUG
void SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over,
const SkOpGlobalState* debugState) const {
- SkASSERT(coinPtTEnd()->span() == over || !debugState->debugRunFail());
- SkASSERT(oppPtTEnd()->span() == outer || !debugState->debugRunFail());
+ SkASSERT(coinPtTEnd()->span() == over || !SkOpGlobalState::DebugRunFail());
+ SkASSERT(oppPtTEnd()->span() == outer || !SkOpGlobalState::DebugRunFail());
}
#endif
@@ -2906,3 +2905,203 @@ void SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool incl
iter.setPath(path);
showPathContours(iter, name);
}
+
+#ifdef SK_DEBUG
+#include "SkData.h"
+#include "SkStream.h"
+
+static void dump_path(FILE* file, const SkPath& path, bool force, bool dumpAsHex) {
+ SkDynamicMemoryWStream wStream;
+ path.dump(&wStream, force, dumpAsHex);
+ sk_sp<SkData> data(wStream.detachAsData());
+ fprintf(file, "%.*s\n", (int) data->size(), (char*) data->data());
+}
+
+static int dumpID = 0;
+
+void SkPathOpsDebug::DumpOp(const SkPath& one, const SkPath& two, SkPathOp op,
+ const char* testName) {
+ FILE* file = sk_fopen("op_dump.txt", kWrite_SkFILE_Flag);
+ DumpOp(file, one, two, op, testName);
+}
+
+void SkPathOpsDebug::DumpOp(FILE* file, const SkPath& one, const SkPath& two, SkPathOp op,
+ const char* testName) {
+ const char* name = testName ? testName : "op";
+ fprintf(file,
+ "\nstatic void %s_%d(skiatest::Reporter* reporter, const char* filename) {\n",
+ name, ++dumpID);
+ fprintf(file, " SkPath path;\n");
+ fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", one.getFillType());
+ dump_path(file, one, false, true);
+ fprintf(file, " SkPath path1(path);\n");
+ fprintf(file, " path.reset();\n");
+ fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", two.getFillType());
+ dump_path(file, two, false, true);
+ fprintf(file, " SkPath path2(path);\n");
+ fprintf(file, " testPathOp(reporter, path1, path2, (SkPathOp) %d, filename);\n", op);
+ fprintf(file, "}\n\n");
+ fclose(file);
+}
+
+void SkPathOpsDebug::DumpSimplify(const SkPath& path, const char* testName) {
+ FILE* file = sk_fopen("simplify_dump.txt", kWrite_SkFILE_Flag);
+ DumpSimplify(file, path, testName);
+}
+
+void SkPathOpsDebug::DumpSimplify(FILE* file, const SkPath& path, const char* testName) {
+ const char* name = testName ? testName : "simplify";
+ fprintf(file,
+ "\nstatic void %s_%d(skiatest::Reporter* reporter, const char* filename) {\n",
+ name, ++dumpID);
+ fprintf(file, " SkPath path;\n");
+ fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", path.getFillType());
+ dump_path(file, path, false, true);
+ fprintf(file, " testSimplify(reporter, path, filename);\n");
+ fprintf(file, "}\n\n");
+ fclose(file);
+}
+
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+
+const int bitWidth = 64;
+const int bitHeight = 64;
+
+static void debug_scale_matrix(const SkPath& one, const SkPath* two, SkMatrix& scale) {
+ SkRect larger = one.getBounds();
+ if (two) {
+ larger.join(two->getBounds());
+ }
+ SkScalar largerWidth = larger.width();
+ if (largerWidth < 4) {
+ largerWidth = 4;
+ }
+ SkScalar largerHeight = larger.height();
+ if (largerHeight < 4) {
+ largerHeight = 4;
+ }
+ SkScalar hScale = (bitWidth - 2) / largerWidth;
+ SkScalar vScale = (bitHeight - 2) / largerHeight;
+ scale.reset();
+ scale.preScale(hScale, vScale);
+ larger.fLeft *= hScale;
+ larger.fRight *= hScale;
+ larger.fTop *= vScale;
+ larger.fBottom *= vScale;
+ SkScalar dx = -16000 > larger.fLeft ? -16000 - larger.fLeft
+ : 16000 < larger.fRight ? 16000 - larger.fRight : 0;
+ SkScalar dy = -16000 > larger.fTop ? -16000 - larger.fTop
+ : 16000 < larger.fBottom ? 16000 - larger.fBottom : 0;
+ scale.preTranslate(dx, dy);
+}
+
+static int debug_paths_draw_the_same(const SkPath& one, const SkPath& two, SkBitmap& bits) {
+ if (bits.width() == 0) {
+ bits.allocN32Pixels(bitWidth * 2, bitHeight);
+ }
+ SkCanvas canvas(bits);
+ canvas.drawColor(SK_ColorWHITE);
+ SkPaint paint;
+ canvas.save();
+ const SkRect& bounds1 = one.getBounds();
+ canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
+ canvas.drawPath(one, paint);
+ canvas.restore();
+ canvas.save();
+ canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
+ canvas.drawPath(two, paint);
+ canvas.restore();
+ int errors = 0;
+ for (int y = 0; y < bitHeight - 1; ++y) {
+ uint32_t* addr1 = bits.getAddr32(0, y);
+ uint32_t* addr2 = bits.getAddr32(0, y + 1);
+ uint32_t* addr3 = bits.getAddr32(bitWidth, y);
+ uint32_t* addr4 = bits.getAddr32(bitWidth, y + 1);
+ for (int x = 0; x < bitWidth - 1; ++x) {
+ // count 2x2 blocks
+ bool err = addr1[x] != addr3[x];
+ if (err) {
+ errors += addr1[x + 1] != addr3[x + 1]
+ && addr2[x] != addr4[x] && addr2[x + 1] != addr4[x + 1];
+ }
+ }
+ }
+ return errors;
+}
+
+void SkPathOpsDebug::ReportOpFail(const SkPath& one, const SkPath& two, SkPathOp op) {
+ SkDebugf("// Op did not expect failure\n");
+ DumpOp(stderr, one, two, op, "opTest");
+ fflush(stderr);
+}
+
+void SkPathOpsDebug::VerifyOp(const SkPath& one, const SkPath& two, SkPathOp op,
+ const SkPath& result) {
+ SkPath pathOut, scaledPathOut;
+ SkRegion rgnA, rgnB, openClip, rgnOut;
+ openClip.setRect(-16000, -16000, 16000, 16000);
+ rgnA.setPath(one, openClip);
+ rgnB.setPath(two, openClip);
+ rgnOut.op(rgnA, rgnB, (SkRegion::Op) op);
+ rgnOut.getBoundaryPath(&pathOut);
+ SkMatrix scale;
+ debug_scale_matrix(one, &two, scale);
+ SkRegion scaledRgnA, scaledRgnB, scaledRgnOut;
+ SkPath scaledA, scaledB;
+ scaledA.addPath(one, scale);
+ scaledA.setFillType(one.getFillType());
+ scaledB.addPath(two, scale);
+ scaledB.setFillType(two.getFillType());
+ scaledRgnA.setPath(scaledA, openClip);
+ scaledRgnB.setPath(scaledB, openClip);
+ scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) op);
+ scaledRgnOut.getBoundaryPath(&scaledPathOut);
+ SkBitmap bitmap;
+ SkPath scaledOut;
+ scaledOut.addPath(result, scale);
+ scaledOut.setFillType(result.getFillType());
+ int errors = debug_paths_draw_the_same(scaledPathOut, scaledOut, bitmap);
+ const int MAX_ERRORS = 9;
+ if (errors > MAX_ERRORS) {
+ fprintf(stderr, "// Op did not expect errors=%d\n", errors);
+ DumpOp(stderr, one, two, op, "opTest");
+ fflush(stderr);
+ }
+}
+
+void SkPathOpsDebug::ReportSimplifyFail(const SkPath& path) {
+ SkDebugf("// Simplify did not expect failure\n");
+ DumpSimplify(stderr, path, "simplifyTest");
+ fflush(stderr);
+}
+
+void SkPathOpsDebug::VerifySimplify(const SkPath& path, const SkPath& result) {
+ SkPath pathOut, scaledPathOut;
+ SkRegion rgnA, openClip, rgnOut;
+ openClip.setRect(-16000, -16000, 16000, 16000);
+ rgnA.setPath(path, openClip);
+ rgnOut.getBoundaryPath(&pathOut);
+ SkMatrix scale;
+ debug_scale_matrix(path, nullptr, scale);
+ SkRegion scaledRgnA;
+ SkPath scaledA;
+ scaledA.addPath(path, scale);
+ scaledA.setFillType(path.getFillType());
+ scaledRgnA.setPath(scaledA, openClip);
+ scaledRgnA.getBoundaryPath(&scaledPathOut);
+ SkBitmap bitmap;
+ SkPath scaledOut;
+ scaledOut.addPath(result, scale);
+ scaledOut.setFillType(result.getFillType());
+ int errors = debug_paths_draw_the_same(scaledPathOut, scaledOut, bitmap);
+ const int MAX_ERRORS = 9;
+ if (errors > MAX_ERRORS) {
+ fprintf(stderr, "// Simplify did not expect errors=%d\n", errors);
+ DumpSimplify(stderr, path, "simplifyTest");
+ fflush(stderr);
+ }
+}
+
+#endif
« no previous file with comments | « src/pathops/SkPathOpsDebug.h ('k') | src/pathops/SkPathOpsOp.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698