blob: ebc6e140ed11083abcf0f52a534e55b96058a52c [file] [log] [blame]
caryclark@google.comcd4421d2012-03-01 19:16:31 +00001#include "EdgeWalker_Test.h"
2#include "Intersection_Tests.h"
3#include "SkBitmap.h"
4#include "SkCanvas.h"
5#include "SkPaint.h"
caryclark@google.com59823f72012-08-09 18:17:47 +00006#include "SkStream.h"
7
caryclark@google.comfb173422012-04-10 18:28:55 +00008#include <algorithm>
caryclark@google.com59823f72012-08-09 18:17:47 +00009#include <assert.h>
10#include <errno.h>
11#include <pthread.h>
12#include <unistd.h>
13#include <sys/types.h>
14#include <sys/sysctl.h>
caryclark@google.comcd4421d2012-03-01 19:16:31 +000015
caryclark@google.com78e17132012-04-17 11:40:34 +000016#undef SkASSERT
17#define SkASSERT(cond) while (!(cond)) { sk_throw(); }
18
caryclark@google.com59823f72012-08-09 18:17:47 +000019static const char marker[] =
20 "</div>\n"
21 "\n"
22 "<script type=\"text/javascript\">\n"
23 "\n"
24 "var testDivs = [\n";
caryclark@google.com24bec792012-08-20 12:43:57 +000025
26static const char preferredFilename[] = "/flash/debug/XX.txt";
27static const char backupFilename[] = "../../experimental/Intersection/debugXX.txt";
caryclark@google.com59823f72012-08-09 18:17:47 +000028
caryclark@google.com2e7f4c82012-03-20 21:11:59 +000029static bool gShowPath = false;
caryclark@google.com198e0542012-03-30 18:47:02 +000030static bool gComparePaths = true;
caryclark@google.coma3f05fa2012-06-01 17:44:28 +000031//static bool gDrawLastAsciiPaths = true;
caryclark@google.comcd4421d2012-03-01 19:16:31 +000032static bool gDrawAllAsciiPaths = false;
caryclark@google.com2e7f4c82012-03-20 21:11:59 +000033static bool gShowAsciiPaths = false;
caryclark@google.com59823f72012-08-09 18:17:47 +000034static bool gComparePathsAssert = false;
35static bool gPathStrAssert = true;
caryclark@google.comcd4421d2012-03-01 19:16:31 +000036
caryclark@google.com2e7f4c82012-03-20 21:11:59 +000037void showPath(const SkPath& path, const char* str) {
caryclark@google.com752b60e2012-03-22 21:11:17 +000038 SkDebugf("%s\n", !str ? "original:" : str);
caryclark@google.comcd4421d2012-03-01 19:16:31 +000039 SkPath::Iter iter(path, true);
40 uint8_t verb;
41 SkPoint pts[4];
42 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
43 switch (verb) {
44 case SkPath::kMove_Verb:
caryclark@google.comd88e0892012-03-27 13:23:51 +000045 SkDebugf("path.moveTo(%1.9g, %1.9g);\n", pts[0].fX, pts[0].fY);
caryclark@google.comcd4421d2012-03-01 19:16:31 +000046 continue;
47 case SkPath::kLine_Verb:
caryclark@google.comd88e0892012-03-27 13:23:51 +000048 SkDebugf("path.lineTo(%1.9g, %1.9g);\n", pts[1].fX, pts[1].fY);
caryclark@google.comcd4421d2012-03-01 19:16:31 +000049 break;
50 case SkPath::kQuad_Verb:
caryclark@google.comd88e0892012-03-27 13:23:51 +000051 SkDebugf("path.quadTo(%1.9g, %1.9g, %1.9g, %1.9g);\n",
caryclark@google.comcd4421d2012-03-01 19:16:31 +000052 pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
53 break;
54 case SkPath::kCubic_Verb:
caryclark@google.comd88e0892012-03-27 13:23:51 +000055 SkDebugf("path.cubicTo(%1.9g, %1.9g, %1.9g, %1.9g);\n",
caryclark@google.comcd4421d2012-03-01 19:16:31 +000056 pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY,
57 pts[3].fX, pts[3].fY);
58 break;
59 case SkPath::kClose_Verb:
60 SkDebugf("path.close();\n");
61 continue;
62 default:
63 SkDEBUGFAIL("bad verb");
64 return;
65 }
66 }
67}
68
caryclark@google.com198e0542012-03-30 18:47:02 +000069static int pathsDrawTheSame(const SkPath& one, const SkPath& two,
70 SkBitmap& bits, SkCanvas* c) {
71 SkCanvas* canvasPtr = c;
72 if (!c) {
73 canvasPtr = new SkCanvas(bits);
74 }
caryclark@google.comcd4421d2012-03-01 19:16:31 +000075 const SkRect& bounds1 = one.getBounds();
76 const SkRect& bounds2 = two.getBounds();
77 SkRect larger = bounds1;
78 larger.join(bounds2);
caryclark@google.comcd4421d2012-03-01 19:16:31 +000079 int bitWidth = SkScalarCeil(larger.width()) + 2;
80 int bitHeight = SkScalarCeil(larger.height()) + 2;
caryclark@google.com198e0542012-03-30 18:47:02 +000081 if (bits.width() < bitWidth * 2 || bits.height() < bitHeight) {
caryclark@google.com8dcf1142012-07-02 20:27:02 +000082 if (bits.width() >= 200 && false) {
caryclark@google.com198e0542012-03-30 18:47:02 +000083 SkDebugf("%s bitWidth=%d bitHeight=%d\n", __FUNCTION__, bitWidth, bitHeight);
84 }
85 bits.setConfig(SkBitmap::kARGB_8888_Config, bitWidth * 2, bitHeight);
86 bits.allocPixels();
87 canvasPtr->setBitmapDevice(bits);
88 }
89 SkCanvas& canvas = *canvasPtr;
caryclark@google.comcd4421d2012-03-01 19:16:31 +000090 canvas.drawColor(SK_ColorWHITE);
91 SkPaint paint;
92 canvas.save();
93 canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
94 canvas.drawPath(one, paint);
95 canvas.restore();
96 canvas.save();
97 canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
98 canvas.drawPath(two, paint);
99 canvas.restore();
caryclark@google.com198e0542012-03-30 18:47:02 +0000100 int errors = 0;
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000101 for (int y = 0; y < bitHeight; ++y) {
102 uint32_t* addr1 = bits.getAddr32(0, y);
103 uint32_t* addr2 = bits.getAddr32(bitWidth, y);
104 for (int x = 0; x < bitWidth; ++x) {
caryclark@google.com198e0542012-03-30 18:47:02 +0000105 errors += addr1[x] != addr2[x];
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000106 }
107 }
caryclark@google.com198e0542012-03-30 18:47:02 +0000108 if (!c) {
109 delete canvasPtr;
110 }
111 return errors;
112}
113
caryclark@google.com752b60e2012-03-22 21:11:17 +0000114bool drawAsciiPaths(const SkPath& one, const SkPath& two,
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000115 bool drawPaths) {
116 if (!drawPaths) {
caryclark@google.com752b60e2012-03-22 21:11:17 +0000117 return true;
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000118 }
caryclark@google.com2e7f4c82012-03-20 21:11:59 +0000119 if (gShowAsciiPaths) {
120 showPath(one, "one:");
121 showPath(two, "two:");
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000122 }
123 const SkRect& bounds1 = one.getBounds();
124 const SkRect& bounds2 = two.getBounds();
125 SkRect larger = bounds1;
126 larger.join(bounds2);
127 SkBitmap bits;
caryclark@google.com752b60e2012-03-22 21:11:17 +0000128 char out[256];
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000129 int bitWidth = SkScalarCeil(larger.width()) + 2;
caryclark@google.com752b60e2012-03-22 21:11:17 +0000130 if (bitWidth * 2 + 1 >= (int) sizeof(out)) {
131 return false;
132 }
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000133 int bitHeight = SkScalarCeil(larger.height()) + 2;
caryclark@google.com752b60e2012-03-22 21:11:17 +0000134 if (bitHeight >= (int) sizeof(out)) {
135 return false;
136 }
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000137 bits.setConfig(SkBitmap::kARGB_8888_Config, bitWidth * 2, bitHeight);
138 bits.allocPixels();
139 SkCanvas canvas(bits);
140 canvas.drawColor(SK_ColorWHITE);
141 SkPaint paint;
142 canvas.save();
143 canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
144 canvas.drawPath(one, paint);
145 canvas.restore();
146 canvas.save();
caryclark@google.comfb173422012-04-10 18:28:55 +0000147 canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000148 canvas.drawPath(two, paint);
149 canvas.restore();
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000150 for (int y = 0; y < bitHeight; ++y) {
151 uint32_t* addr1 = bits.getAddr32(0, y);
152 int x;
153 char* outPtr = out;
154 for (x = 0; x < bitWidth; ++x) {
155 *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
156 }
157 *outPtr++ = '|';
158 for (x = bitWidth; x < bitWidth * 2; ++x) {
159 *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
160 }
161 *outPtr++ = '\0';
162 SkDebugf("%s\n", out);
163 }
caryclark@google.com752b60e2012-03-22 21:11:17 +0000164 return true;
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000165}
166
caryclark@google.com198e0542012-03-30 18:47:02 +0000167static int scaledDrawTheSame(const SkPath& one, const SkPath& two,
caryclark@google.coma3f05fa2012-06-01 17:44:28 +0000168 SkScalar a, SkScalar b, bool drawPaths, SkBitmap& bitmap,
169 SkCanvas* canvas) {
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000170 SkMatrix scale;
171 scale.reset();
caryclark@google.com752b60e2012-03-22 21:11:17 +0000172 float aScale = 1.21f;
173 float bScale = 1.11f;
174 scale.preScale(a * aScale, b * bScale);
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000175 SkPath scaledOne, scaledTwo;
176 one.transform(scale, &scaledOne);
177 two.transform(scale, &scaledTwo);
caryclark@google.com198e0542012-03-30 18:47:02 +0000178 int errors = pathsDrawTheSame(scaledOne, scaledTwo, bitmap, canvas);
179 if (errors == 0) {
180 return 0;
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000181 }
caryclark@google.com752b60e2012-03-22 21:11:17 +0000182 while (!drawAsciiPaths(scaledOne, scaledTwo, drawPaths)) {
183 scale.reset();
184 aScale *= 0.5f;
185 bScale *= 0.5f;
186 scale.preScale(a * aScale, b * bScale);
187 one.transform(scale, &scaledOne);
188 two.transform(scale, &scaledTwo);
189 }
caryclark@google.com198e0542012-03-30 18:47:02 +0000190 return errors;
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000191}
192
caryclark@google.com78e17132012-04-17 11:40:34 +0000193static int max = 0;
194
caryclark@google.com1577e8f2012-05-22 17:01:14 +0000195int comparePaths(const SkPath& one, const SkPath& two, SkBitmap& bitmap,
caryclark@google.com198e0542012-03-30 18:47:02 +0000196 SkCanvas* canvas) {
197 int errors = pathsDrawTheSame(one, two, bitmap, canvas);
198 if (errors == 0) {
199 return 0;
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000200 }
201 drawAsciiPaths(one, two, gDrawAllAsciiPaths);
202 for (int x = 9; x <= 33; ++x) {
caryclark@google.com198e0542012-03-30 18:47:02 +0000203 errors = scaledDrawTheSame(one, two, x, x - (x >> 2), gDrawAllAsciiPaths,
204 bitmap, canvas);
205 if (errors == 0) {
206 return 0;
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000207 }
208 }
209 if (!gDrawAllAsciiPaths) {
caryclark@google.comfb173422012-04-10 18:28:55 +0000210 const SkRect& bounds1 = one.getBounds();
211 const SkRect& bounds2 = two.getBounds();
212 SkRect larger = bounds1;
213 larger.join(bounds2);
caryclark@google.com8dcf1142012-07-02 20:27:02 +0000214 SkScalar xScale = std::max(32.0f / larger.width(), 1.0f);
215 SkScalar yScale = std::max(24.0f / larger.height(), 1.0f);
caryclark@google.comfb173422012-04-10 18:28:55 +0000216 errors = scaledDrawTheSame(one, two, xScale, yScale, false, bitmap, canvas);
caryclark@google.com8dcf1142012-07-02 20:27:02 +0000217 if (errors > 5) {
caryclark@google.com59823f72012-08-09 18:17:47 +0000218 SkDebugf("\n");
caryclark@google.comfb173422012-04-10 18:28:55 +0000219 scaledDrawTheSame(one, two, xScale, yScale, true, bitmap, canvas);
caryclark@google.com198e0542012-03-30 18:47:02 +0000220 }
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000221 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000222 const int MAX_ERRORS = 20;
223 if (errors > max && errors <= MAX_ERRORS) {
224 SkDebugf("%s errors=%d\n", __FUNCTION__, errors);
caryclark@google.com78e17132012-04-17 11:40:34 +0000225 max = errors;
226 }
caryclark@google.com78e17132012-04-17 11:40:34 +0000227 if (errors > MAX_ERRORS && gComparePathsAssert) {
caryclark@google.com59823f72012-08-09 18:17:47 +0000228 SkDebugf("%s errors=%d\n", __FUNCTION__, errors);
caryclark@google.com2e7f4c82012-03-20 21:11:59 +0000229 showPath(one);
230 showPath(two, "simplified:");
231 SkASSERT(0);
232 }
caryclark@google.com78e17132012-04-17 11:40:34 +0000233 return errors > MAX_ERRORS ? errors : 0;
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000234}
235
236// doesn't work yet
237void comparePathsTiny(const SkPath& one, const SkPath& two) {
238 const SkRect& bounds1 = one.getBounds();
239 const SkRect& bounds2 = two.getBounds();
240 SkRect larger = bounds1;
241 larger.join(bounds2);
242 SkBitmap bits;
243 int bitWidth = SkScalarCeil(larger.width()) + 2;
244 int bitHeight = SkScalarCeil(larger.height()) + 2;
245 bits.setConfig(SkBitmap::kA1_Config, bitWidth * 2, bitHeight);
246 bits.allocPixels();
247 SkCanvas canvas(bits);
248 canvas.drawColor(SK_ColorWHITE);
249 SkPaint paint;
250 canvas.save();
251 canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
252 canvas.drawPath(one, paint);
253 canvas.restore();
254 canvas.save();
255 canvas.translate(-bounds2.fLeft + 1, -bounds2.fTop + 1);
256 canvas.drawPath(two, paint);
257 canvas.restore();
258 for (int y = 0; y < bitHeight; ++y) {
259 uint8_t* addr1 = bits.getAddr1(0, y);
260 uint8_t* addr2 = bits.getAddr1(bitWidth, y);
261 for (int x = 0; x < bits.rowBytes(); ++x) {
262 SkASSERT(addr1[x] == addr2[x]);
263 }
264 }
265}
266
caryclark@google.com198e0542012-03-30 18:47:02 +0000267bool testSimplify(const SkPath& path, bool fill, SkPath& out, SkBitmap& bitmap,
268 SkCanvas* canvas) {
caryclark@google.com2e7f4c82012-03-20 21:11:59 +0000269 if (gShowPath) {
270 showPath(path);
271 }
272 simplify(path, fill, out);
caryclark@google.com752b60e2012-03-22 21:11:17 +0000273 if (!gComparePaths) {
274 return true;
275 }
caryclark@google.com198e0542012-03-30 18:47:02 +0000276 return comparePaths(path, out, bitmap, canvas) == 0;
caryclark@google.com2e7f4c82012-03-20 21:11:59 +0000277}
caryclark@google.com78e17132012-04-17 11:40:34 +0000278
caryclark@google.com24bec792012-08-20 12:43:57 +0000279bool testSimplifyx(SkPath& path, bool useXor, SkPath& out, State4& state,
caryclark@google.com59823f72012-08-09 18:17:47 +0000280 const char* pathStr) {
caryclark@google.com24bec792012-08-20 12:43:57 +0000281 SkPath::FillType fillType = useXor ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType;
282 path.setFillType(fillType);
caryclark@google.com8dcf1142012-07-02 20:27:02 +0000283 if (gShowPath) {
284 showPath(path);
285 }
286 simplifyx(path, out);
287 if (!gComparePaths) {
288 return true;
289 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000290 int result = comparePaths(path, out, state.bitmap, state.canvas);
291 if (result && gPathStrAssert) {
292 char temp[8192];
293 bzero(temp, sizeof(temp));
294 SkMemoryWStream stream(temp, sizeof(temp));
caryclark@google.com24bec792012-08-20 12:43:57 +0000295 outputToStream(state, pathStr, fillType, stream);
caryclark@google.com59823f72012-08-09 18:17:47 +0000296 SkDebugf(temp);
297 SkASSERT(0);
298 }
299 return result == 0;
caryclark@google.com8dcf1142012-07-02 20:27:02 +0000300}
301
302bool testSimplifyx(const SkPath& path) {
caryclark@google.com8dcf1142012-07-02 20:27:02 +0000303 SkPath out;
304 simplifyx(path, out);
caryclark@google.com8dcf1142012-07-02 20:27:02 +0000305 SkBitmap bitmap;
caryclark@google.com24bec792012-08-20 12:43:57 +0000306 int result = comparePaths(path, out, bitmap, 0);
307 if (result && gPathStrAssert) {
308 SkASSERT(0);
309 }
310 return result == 0;
caryclark@google.com8dcf1142012-07-02 20:27:02 +0000311}
312
caryclark@google.com59823f72012-08-09 18:17:47 +0000313const int maxThreadsAllocated = 64;
314static int maxThreads = 1;
315static int threadIndex;
316State4 threadState[maxThreadsAllocated];
317static int testNumber;
318static const char* testName;
319static bool debugThreads = false;
320
321State4* State4::queue = NULL;
322pthread_mutex_t State4::addQueue = PTHREAD_MUTEX_INITIALIZER;
323pthread_cond_t State4::checkQueue = PTHREAD_COND_INITIALIZER;
324
caryclark@google.com78e17132012-04-17 11:40:34 +0000325State4::State4() {
326 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 150 * 2, 100);
327 bitmap.allocPixels();
328 canvas = new SkCanvas(bitmap);
329}
330
caryclark@google.com59823f72012-08-09 18:17:47 +0000331void createThread(State4* statePtr, void* (*testFun)(void* )) {
332 int threadError = pthread_create(&statePtr->threadID, NULL, testFun,
caryclark@google.com78e17132012-04-17 11:40:34 +0000333 (void*) statePtr);
334 SkASSERT(!threadError);
335}
336
caryclark@google.com59823f72012-08-09 18:17:47 +0000337int dispatchTest4(void* (*testFun)(void* ), int a, int b, int c, int d) {
338 int testsRun = 0;
caryclark@google.com03f97062012-08-21 13:13:52 +0000339 State4* statePtr;
caryclark@google.com59823f72012-08-09 18:17:47 +0000340 if (!gRunTestsInOneThread) {
caryclark@google.com59823f72012-08-09 18:17:47 +0000341 pthread_mutex_lock(&State4::addQueue);
342 if (threadIndex < maxThreads) {
343 statePtr = &threadState[threadIndex];
344 statePtr->testsRun = 0;
345 statePtr->a = a;
346 statePtr->b = b;
347 statePtr->c = c;
348 statePtr->d = d;
349 statePtr->done = false;
350 statePtr->index = threadIndex;
351 statePtr->last = false;
352 if (debugThreads) SkDebugf("%s %d create done=%d last=%d\n", __FUNCTION__,
353 statePtr->index, statePtr->done, statePtr->last);
354 pthread_cond_init(&statePtr->initialized, NULL);
355 ++threadIndex;
356 createThread(statePtr, testFun);
357 } else {
358 while (!State4::queue) {
359 if (debugThreads) SkDebugf("%s checkQueue\n", __FUNCTION__);
360 pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
361 }
362 statePtr = State4::queue;
363 testsRun += statePtr->testsRun;
364 statePtr->testsRun = 0;
365 statePtr->a = a;
366 statePtr->b = b;
367 statePtr->c = c;
368 statePtr->d = d;
369 statePtr->done = false;
370 State4::queue = NULL;
371 for (int index = 0; index < maxThreads; ++index) {
372 if (threadState[index].done) {
373 State4::queue = &threadState[index];
374 }
375 }
376 if (debugThreads) SkDebugf("%s %d init done=%d last=%d queued=%d\n", __FUNCTION__,
377 statePtr->index, statePtr->done, statePtr->last,
378 State4::queue ? State4::queue->index : -1);
379 pthread_cond_signal(&statePtr->initialized);
380 }
381 pthread_mutex_unlock(&State4::addQueue);
382 } else {
caryclark@google.com03f97062012-08-21 13:13:52 +0000383 statePtr = &threadState[0];
384 statePtr->testsRun = 0;
385 statePtr->a = a;
386 statePtr->b = b;
387 statePtr->c = c;
388 statePtr->d = d;
389 statePtr->done = false;
390 statePtr->index = threadIndex;
391 statePtr->last = false;
392 (*testFun)(statePtr);
caryclark@google.com59823f72012-08-09 18:17:47 +0000393 testsRun++;
caryclark@google.com78e17132012-04-17 11:40:34 +0000394 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000395 return testsRun;
396}
397
398void initializeTests(const char* test, size_t testNameSize) {
399 testName = test;
400 if (!gRunTestsInOneThread) {
401 int threads = -1;
402 size_t size = sizeof(threads);
403 sysctlbyname("hw.logicalcpu_max", &threads, &size, NULL, 0);
404 if (threads > 0) {
405 maxThreads = threads;
406 } else {
407 maxThreads = 8;
408 }
409 }
caryclark@google.com03f97062012-08-21 13:13:52 +0000410 SkFILEStream inFile("../../experimental/Intersection/op.htm");
411 if (inFile.isValid()) {
412 SkTDArray<char> inData;
413 inData.setCount(inFile.getLength());
414 size_t inLen = inData.count();
415 inFile.read(inData.begin(), inLen);
416 inFile.setPath(NULL);
417 char* insert = strstr(inData.begin(), marker);
418 if (insert) {
419 insert += sizeof(marker) - 1;
420 const char* numLoc = insert + 4 /* indent spaces */ + testNameSize - 1;
421 testNumber = atoi(numLoc) + 1;
caryclark@google.com59823f72012-08-09 18:17:47 +0000422 }
423 }
caryclark@google.com24bec792012-08-20 12:43:57 +0000424 const char* filename = preferredFilename;
425 SkFILEWStream preferredTest(filename);
426 if (!preferredTest.isValid()) {
427 filename = backupFilename;
428 SkFILEWStream backupTest(filename);
429 SkASSERT(backupTest.isValid());
430 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000431 for (int index = 0; index < maxThreads; ++index) {
432 State4* statePtr = &threadState[index];
433 strcpy(statePtr->filename, filename);
caryclark@google.com24bec792012-08-20 12:43:57 +0000434 size_t len = strlen(filename);
435 SkASSERT(statePtr->filename[len - 6] == 'X');
436 SkASSERT(statePtr->filename[len - 5] == 'X');
437 statePtr->filename[len - 6] = '0' + index / 10;
438 statePtr->filename[len - 5] = '0' + index % 10;
caryclark@google.com59823f72012-08-09 18:17:47 +0000439 }
caryclark@google.com78e17132012-04-17 11:40:34 +0000440 threadIndex = 0;
441}
caryclark@google.com59823f72012-08-09 18:17:47 +0000442
caryclark@google.com24bec792012-08-20 12:43:57 +0000443void outputProgress(const State4& state, const char* pathStr, SkPath::FillType pathFillType) {
caryclark@google.com59823f72012-08-09 18:17:47 +0000444 if (gRunTestsInOneThread) {
caryclark@google.com03f97062012-08-21 13:13:52 +0000445 if (pathFillType == SkPath::kEvenOdd_FillType) {
446 SkDebugf(" path.setFillType(SkPath::kEvenOdd_FillType);\n", pathStr);
caryclark@google.com59823f72012-08-09 18:17:47 +0000447 }
caryclark@google.com03f97062012-08-21 13:13:52 +0000448 SkDebugf("%s\n", pathStr);
caryclark@google.com59823f72012-08-09 18:17:47 +0000449 }
caryclark@google.com03f97062012-08-21 13:13:52 +0000450 SkFILEWStream outFile(state.filename);
451 if (!outFile.isValid()) {
452 SkASSERT(0);
453 return;
454 }
455 outputToStream(state, pathStr, pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000456}
457
caryclark@google.com24bec792012-08-20 12:43:57 +0000458static void writeTestName(SkPath::FillType pathFillType, SkWStream& outFile) {
caryclark@google.com59823f72012-08-09 18:17:47 +0000459 outFile.writeText(testName);
460 outFile.writeDecAsText(testNumber);
caryclark@google.com24bec792012-08-20 12:43:57 +0000461 if (pathFillType == SkPath::kEvenOdd_FillType) {
462 outFile.writeText("x");
463 }
464}
465
466void outputToStream(const State4& state, const char* pathStr, SkPath::FillType pathFillType, SkWStream& outFile) {
467 outFile.writeText("<div id=\"");
468 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000469 outFile.writeText("\">\n");
caryclark@google.com24bec792012-08-20 12:43:57 +0000470 if (pathFillType == SkPath::kEvenOdd_FillType) {
471 outFile.writeText(" path.setFillType(SkPath::kEvenOdd_FillType);\n");
472 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000473 outFile.writeText(pathStr);
474 outFile.writeText("</div>\n\n");
475
476 outFile.writeText(marker);
477 outFile.writeText(" ");
caryclark@google.com24bec792012-08-20 12:43:57 +0000478 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000479 outFile.writeText(",\n\n\n");
480
481 outFile.writeText("static void ");
caryclark@google.com24bec792012-08-20 12:43:57 +0000482 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000483 outFile.writeText("() {\n SkPath path;\n");
caryclark@google.com24bec792012-08-20 12:43:57 +0000484 if (pathFillType == SkPath::kEvenOdd_FillType) {
485 outFile.writeText(" path.setFillType(SkPath::kEvenOdd_FillType);\n");
486 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000487 outFile.writeText(pathStr);
488 outFile.writeText(" testSimplifyx(path);\n}\n\n");
489 outFile.writeText("static void (*firstTest)() = ");
caryclark@google.com24bec792012-08-20 12:43:57 +0000490 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000491 outFile.writeText(";\n\n");
492
493 outFile.writeText("static struct {\n");
494 outFile.writeText(" void (*fun)();\n");
495 outFile.writeText(" const char* str;\n");
496 outFile.writeText("} tests[] = {\n");
497 outFile.writeText(" TEST(");
caryclark@google.com24bec792012-08-20 12:43:57 +0000498 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000499 outFile.writeText("),\n");
500 outFile.flush();
501}
502
503bool runNextTestSet(State4& state) {
504 if (gRunTestsInOneThread) {
505 return false;
506 }
507 pthread_mutex_lock(&State4::addQueue);
508 state.done = true;
509 State4::queue = &state;
510 if (debugThreads) SkDebugf("%s %d checkQueue done=%d last=%d\n", __FUNCTION__, state.index,
511 state.done, state.last);
512 pthread_cond_signal(&State4::checkQueue);
513 while (state.done && !state.last) {
514 if (debugThreads) SkDebugf("%s %d done=%d last=%d\n", __FUNCTION__, state.index, state.done, state.last);
515 pthread_cond_wait(&state.initialized, &State4::addQueue);
516 }
517 pthread_mutex_unlock(&State4::addQueue);
518 return !state.last;
519}
520
521int waitForCompletion() {
522 int testsRun = 0;
523 if (!gRunTestsInOneThread) {
524 pthread_mutex_lock(&State4::addQueue);
525 int runningThreads = maxThreads;
526 int index;
527 while (runningThreads > 0) {
528 while (!State4::queue) {
529 if (debugThreads) SkDebugf("%s checkQueue\n", __FUNCTION__);
530 pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
531 }
532 while (State4::queue) {
533 --runningThreads;
534 SkDebugf("•");
535 State4::queue->last = true;
caryclark@google.com24bec792012-08-20 12:43:57 +0000536 State4* next = NULL;
caryclark@google.com59823f72012-08-09 18:17:47 +0000537 for (index = 0; index < maxThreads; ++index) {
538 State4& test = threadState[index];
539 if (test.done && !test.last) {
540 next = &test;
541 }
542 }
543 if (debugThreads) SkDebugf("%s %d next=%d deQueue\n", __FUNCTION__,
544 State4::queue->index, next ? next->index : -1);
545 pthread_cond_signal(&State4::queue->initialized);
546 State4::queue = next;
547 }
548 }
549 pthread_mutex_unlock(&State4::addQueue);
550 for (index = 0; index < maxThreads; ++index) {
551 pthread_join(threadState[index].threadID, NULL);
552 testsRun += threadState[index].testsRun;
553 }
554 SkDebugf("\n");
555 }
556#ifdef SK_DEBUG
557 gDebugMaxWindSum = SK_MaxS32;
558 gDebugMaxWindValue = SK_MaxS32;
559#endif
560 return testsRun;
561}