blob: 0fb37b08402b69950541afd6c9b923eb6238cb27 [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;
339
340 if (!gRunTestsInOneThread) {
341 State4* statePtr;
342 pthread_mutex_lock(&State4::addQueue);
343 if (threadIndex < maxThreads) {
344 statePtr = &threadState[threadIndex];
345 statePtr->testsRun = 0;
346 statePtr->a = a;
347 statePtr->b = b;
348 statePtr->c = c;
349 statePtr->d = d;
350 statePtr->done = false;
351 statePtr->index = threadIndex;
352 statePtr->last = false;
353 if (debugThreads) SkDebugf("%s %d create done=%d last=%d\n", __FUNCTION__,
354 statePtr->index, statePtr->done, statePtr->last);
355 pthread_cond_init(&statePtr->initialized, NULL);
356 ++threadIndex;
357 createThread(statePtr, testFun);
358 } else {
359 while (!State4::queue) {
360 if (debugThreads) SkDebugf("%s checkQueue\n", __FUNCTION__);
361 pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
362 }
363 statePtr = State4::queue;
364 testsRun += statePtr->testsRun;
365 statePtr->testsRun = 0;
366 statePtr->a = a;
367 statePtr->b = b;
368 statePtr->c = c;
369 statePtr->d = d;
370 statePtr->done = false;
371 State4::queue = NULL;
372 for (int index = 0; index < maxThreads; ++index) {
373 if (threadState[index].done) {
374 State4::queue = &threadState[index];
375 }
376 }
377 if (debugThreads) SkDebugf("%s %d init done=%d last=%d queued=%d\n", __FUNCTION__,
378 statePtr->index, statePtr->done, statePtr->last,
379 State4::queue ? State4::queue->index : -1);
380 pthread_cond_signal(&statePtr->initialized);
381 }
382 pthread_mutex_unlock(&State4::addQueue);
383 } else {
384 State4 state;
385 state.a = a;
386 state.b = b;
387 state.c = c;
388 state.d = d;
389 (*testFun)(&state);
390 testsRun++;
caryclark@google.com78e17132012-04-17 11:40:34 +0000391 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000392 return testsRun;
393}
394
395void initializeTests(const char* test, size_t testNameSize) {
396 testName = test;
397 if (!gRunTestsInOneThread) {
398 int threads = -1;
399 size_t size = sizeof(threads);
400 sysctlbyname("hw.logicalcpu_max", &threads, &size, NULL, 0);
401 if (threads > 0) {
402 maxThreads = threads;
403 } else {
404 maxThreads = 8;
405 }
406 }
407 if (!gRunTestsInOneThread) {
408 SkFILEStream inFile("../../experimental/Intersection/op.htm");
409 if (inFile.isValid()) {
410 SkTDArray<char> inData;
411 inData.setCount(inFile.getLength());
412 size_t inLen = inData.count();
413 inFile.read(inData.begin(), inLen);
414 inFile.setPath(NULL);
415 char* insert = strstr(inData.begin(), marker);
416 if (insert) {
417 insert += sizeof(marker) - 1;
418 const char* numLoc = insert + 4 /* indent spaces */ + testNameSize - 1;
419 testNumber = atoi(numLoc) + 1;
420 }
421 }
422 }
caryclark@google.com24bec792012-08-20 12:43:57 +0000423 const char* filename = preferredFilename;
424 SkFILEWStream preferredTest(filename);
425 if (!preferredTest.isValid()) {
426 filename = backupFilename;
427 SkFILEWStream backupTest(filename);
428 SkASSERT(backupTest.isValid());
429 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000430 for (int index = 0; index < maxThreads; ++index) {
431 State4* statePtr = &threadState[index];
432 strcpy(statePtr->filename, filename);
caryclark@google.com24bec792012-08-20 12:43:57 +0000433 size_t len = strlen(filename);
434 SkASSERT(statePtr->filename[len - 6] == 'X');
435 SkASSERT(statePtr->filename[len - 5] == 'X');
436 statePtr->filename[len - 6] = '0' + index / 10;
437 statePtr->filename[len - 5] = '0' + index % 10;
caryclark@google.com59823f72012-08-09 18:17:47 +0000438 }
caryclark@google.com78e17132012-04-17 11:40:34 +0000439 threadIndex = 0;
440}
caryclark@google.com59823f72012-08-09 18:17:47 +0000441
caryclark@google.com24bec792012-08-20 12:43:57 +0000442void outputProgress(const State4& state, const char* pathStr, SkPath::FillType pathFillType) {
caryclark@google.com59823f72012-08-09 18:17:47 +0000443 if (gRunTestsInOneThread) {
444 SkDebugf("%s\n", pathStr);
445 } else {
446 SkFILEWStream outFile(state.filename);
447 if (!outFile.isValid()) {
448 SkASSERT(0);
449 return;
450 }
caryclark@google.com24bec792012-08-20 12:43:57 +0000451 outputToStream(state, pathStr, pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000452 }
453}
454
caryclark@google.com24bec792012-08-20 12:43:57 +0000455static void writeTestName(SkPath::FillType pathFillType, SkWStream& outFile) {
caryclark@google.com59823f72012-08-09 18:17:47 +0000456 outFile.writeText(testName);
457 outFile.writeDecAsText(testNumber);
caryclark@google.com24bec792012-08-20 12:43:57 +0000458 if (pathFillType == SkPath::kEvenOdd_FillType) {
459 outFile.writeText("x");
460 }
461}
462
463void outputToStream(const State4& state, const char* pathStr, SkPath::FillType pathFillType, SkWStream& outFile) {
464 outFile.writeText("<div id=\"");
465 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000466 outFile.writeText("\">\n");
caryclark@google.com24bec792012-08-20 12:43:57 +0000467 if (pathFillType == SkPath::kEvenOdd_FillType) {
468 outFile.writeText(" path.setFillType(SkPath::kEvenOdd_FillType);\n");
469 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000470 outFile.writeText(pathStr);
471 outFile.writeText("</div>\n\n");
472
473 outFile.writeText(marker);
474 outFile.writeText(" ");
caryclark@google.com24bec792012-08-20 12:43:57 +0000475 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000476 outFile.writeText(",\n\n\n");
477
478 outFile.writeText("static void ");
caryclark@google.com24bec792012-08-20 12:43:57 +0000479 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000480 outFile.writeText("() {\n SkPath path;\n");
caryclark@google.com24bec792012-08-20 12:43:57 +0000481 if (pathFillType == SkPath::kEvenOdd_FillType) {
482 outFile.writeText(" path.setFillType(SkPath::kEvenOdd_FillType);\n");
483 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000484 outFile.writeText(pathStr);
485 outFile.writeText(" testSimplifyx(path);\n}\n\n");
486 outFile.writeText("static void (*firstTest)() = ");
caryclark@google.com24bec792012-08-20 12:43:57 +0000487 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000488 outFile.writeText(";\n\n");
489
490 outFile.writeText("static struct {\n");
491 outFile.writeText(" void (*fun)();\n");
492 outFile.writeText(" const char* str;\n");
493 outFile.writeText("} tests[] = {\n");
494 outFile.writeText(" TEST(");
caryclark@google.com24bec792012-08-20 12:43:57 +0000495 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000496 outFile.writeText("),\n");
497 outFile.flush();
498}
499
500bool runNextTestSet(State4& state) {
501 if (gRunTestsInOneThread) {
502 return false;
503 }
504 pthread_mutex_lock(&State4::addQueue);
505 state.done = true;
506 State4::queue = &state;
507 if (debugThreads) SkDebugf("%s %d checkQueue done=%d last=%d\n", __FUNCTION__, state.index,
508 state.done, state.last);
509 pthread_cond_signal(&State4::checkQueue);
510 while (state.done && !state.last) {
511 if (debugThreads) SkDebugf("%s %d done=%d last=%d\n", __FUNCTION__, state.index, state.done, state.last);
512 pthread_cond_wait(&state.initialized, &State4::addQueue);
513 }
514 pthread_mutex_unlock(&State4::addQueue);
515 return !state.last;
516}
517
518int waitForCompletion() {
519 int testsRun = 0;
520 if (!gRunTestsInOneThread) {
521 pthread_mutex_lock(&State4::addQueue);
522 int runningThreads = maxThreads;
523 int index;
524 while (runningThreads > 0) {
525 while (!State4::queue) {
526 if (debugThreads) SkDebugf("%s checkQueue\n", __FUNCTION__);
527 pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
528 }
529 while (State4::queue) {
530 --runningThreads;
531 SkDebugf("•");
532 State4::queue->last = true;
caryclark@google.com24bec792012-08-20 12:43:57 +0000533 State4* next = NULL;
caryclark@google.com59823f72012-08-09 18:17:47 +0000534 for (index = 0; index < maxThreads; ++index) {
535 State4& test = threadState[index];
536 if (test.done && !test.last) {
537 next = &test;
538 }
539 }
540 if (debugThreads) SkDebugf("%s %d next=%d deQueue\n", __FUNCTION__,
541 State4::queue->index, next ? next->index : -1);
542 pthread_cond_signal(&State4::queue->initialized);
543 State4::queue = next;
544 }
545 }
546 pthread_mutex_unlock(&State4::addQueue);
547 for (index = 0; index < maxThreads; ++index) {
548 pthread_join(threadState[index].threadID, NULL);
549 testsRun += threadState[index].testsRun;
550 }
551 SkDebugf("\n");
552 }
553#ifdef SK_DEBUG
554 gDebugMaxWindSum = SK_MaxS32;
555 gDebugMaxWindValue = SK_MaxS32;
556#endif
557 return testsRun;
558}