1 #if !SK_SUPPORT_GPU 2 #error "GPU support required" 3 #endif 4 5 #include "GrContext.h" 6 #include "GrContextFactory.h" 7 #include "GrRenderTarget.h" 8 #include "SkGpuDevice.h" 9 #include "gl/GrGLDefines.h" 10 11 #include "SkBitmap.h" 12 #include "SkCanvas.h" 13 #include "SkColor.h" 14 #include "SkDevice.h" 15 #include "SkGraphics.h" 16 #include "SkImageDecoder.h" 17 #include "SkImageEncoder.h" 18 #include "SkOSFile.h" 19 #include "SkPicture.h" 20 #include "SkRTConf.h" 21 #include "SkRunnable.h" 22 #include "SkStream.h" 23 #include "SkString.h" 24 #include "SkTArray.h" 25 #include "SkTDArray.h" 26 #include "SkTaskGroup.h" 27 #include "SkTime.h" 28 #include "Test.h" 29 30 #ifdef SK_BUILD_FOR_WIN 31 #define PATH_SLASH "\\" 32 #define IN_DIR "D:\\9-30-13\\" 33 #define OUT_DIR "D:\\skpSkGr\\11\\" 34 #define LINE_FEED "\r\n" 35 #else 36 #define PATH_SLASH "/" 37 #define IN_DIR "/usr/local/google/home/caryclark" PATH_SLASH "9-30-13-skp" 38 #define OUT_DIR "/media/01CD75512A7F9EE0/4" PATH_SLASH 39 #define LINE_FEED "\n" 40 #endif 41 42 #define PATH_STR_SIZE 512 43 44 static const struct { 45 int directory; 46 const char* filename; 47 } skipOverSkGr[] = { 48 {1, "http___accuweather_com_.skp"}, // Couldn't convert bitmap to texture.http___absoku072_com_ 49 }; 50 51 static const size_t skipOverSkGrCount = SK_ARRAY_COUNT(skipOverSkGr); 52 53 ///////////////////////////////////////// 54 55 class SkpSkGrThreadedRunnable; 56 57 enum TestStep { 58 kCompareBits, 59 kEncodeFiles, 60 }; 61 62 enum { 63 kMaxLength = 128, 64 kMaxFiles = 128, 65 }; 66 67 struct TestResult { 68 void init(int dirNo) { 69 fDirNo = dirNo; 70 sk_bzero(fFilename, sizeof(fFilename)); 71 fTestStep = kCompareBits; 72 fScaleOversized = true; 73 } 74 75 SkString status() { 76 SkString outStr; 77 outStr.printf("%s %d %d%s", fFilename, fPixelError, fTime, LINE_FEED); 78 return outStr; 79 } 80 81 static void Test(int dirNo, const char* filename, TestStep testStep, bool verbose) { 82 TestResult test; 83 test.init(dirNo); 84 test.fTestStep = testStep; 85 strcpy(test.fFilename, filename); 86 test.testOne(); 87 if (verbose) { 88 SkDebugf("%s", test.status().c_str()); 89 } 90 } 91 92 void test(int dirNo, const SkString& filename) { 93 init(dirNo); 94 strcpy(fFilename, filename.c_str()); 95 testOne(); 96 } 97 98 void testOne(); 99 100 char fFilename[kMaxLength]; 101 TestStep fTestStep; 102 int fDirNo; 103 int fPixelError; 104 int fTime; 105 bool fScaleOversized; 106 }; 107 108 struct SkpSkGrThreadState { 109 void init(int dirNo) { 110 fResult.init(dirNo); 111 fFoundCount = 0; 112 fSmallestError = 0; 113 sk_bzero(fFilesFound, sizeof(fFilesFound)); 114 sk_bzero(fDirsFound, sizeof(fDirsFound)); 115 sk_bzero(fError, sizeof(fError)); 116 } 117 118 char fFilesFound[kMaxFiles][kMaxLength]; 119 int fDirsFound[kMaxFiles]; 120 int fError[kMaxFiles]; 121 int fFoundCount; 122 int fSmallestError; 123 skiatest::Reporter* fReporter; 124 TestResult fResult; 125 }; 126 127 struct SkpSkGrThreadedTestRunner { 128 SkpSkGrThreadedTestRunner(skiatest::Reporter* reporter) 129 : fReporter(reporter) { 130 } 131 132 ~SkpSkGrThreadedTestRunner(); 133 void render(); 134 SkTDArray<SkpSkGrThreadedRunnable*> fRunnables; 135 skiatest::Reporter* fReporter; 136 }; 137 138 class SkpSkGrThreadedRunnable : public SkRunnable { 139 public: 140 SkpSkGrThreadedRunnable(void (*testFun)(SkpSkGrThreadState*), int dirNo, const char* str, 141 SkpSkGrThreadedTestRunner* runner) { 142 SkASSERT(strlen(str) < sizeof(fState.fResult.fFilename) - 1); 143 fState.init(dirNo); 144 strcpy(fState.fResult.fFilename, str); 145 fState.fReporter = runner->fReporter; 146 fTestFun = testFun; 147 } 148 149 void run() override { 150 SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024); 151 (*fTestFun)(&fState); 152 } 153 154 SkpSkGrThreadState fState; 155 void (*fTestFun)(SkpSkGrThreadState*); 156 }; 157 158 SkpSkGrThreadedTestRunner::~SkpSkGrThreadedTestRunner() { 159 for (int index = 0; index < fRunnables.count(); index++) { 160 SkDELETE(fRunnables[index]); 161 } 162 } 163 164 void SkpSkGrThreadedTestRunner::render() { 165 SkTaskGroup tg; 166 for (int index = 0; index < fRunnables.count(); ++ index) { 167 tg.add(fRunnables[index]); 168 } 169 } 170 171 //////////////////////////////////////////////// 172 173 static const char outGrDir[] = OUT_DIR "grTest"; 174 static const char outSkDir[] = OUT_DIR "skTest"; 175 static const char outSkpDir[] = OUT_DIR "skpTest"; 176 static const char outDiffDir[] = OUT_DIR "outTest"; 177 static const char outStatusDir[] = OUT_DIR "statusTest"; 178 179 static SkString make_filepath(int dirIndex, const char* dir, const char* name) { 180 SkString path(dir); 181 if (dirIndex) { 182 path.appendf("%d", dirIndex); 183 } 184 path.append(PATH_SLASH); 185 path.append(name); 186 return path; 187 } 188 189 static SkString make_in_dir_name(int dirIndex) { 190 SkString dirName(IN_DIR); 191 dirName.appendf("%d", dirIndex); 192 if (!sk_exists(dirName.c_str())) { 193 SkDebugf("could not read dir %s\n", dirName.c_str()); 194 return SkString(); 195 } 196 return dirName; 197 } 198 199 static bool make_out_dirs() { 200 SkString outDir = make_filepath(0, OUT_DIR, ""); 201 if (!sk_exists(outDir.c_str())) { 202 if (!sk_mkdir(outDir.c_str())) { 203 SkDebugf("could not create dir %s\n", outDir.c_str()); 204 return false; 205 } 206 } 207 SkString grDir = make_filepath(0, outGrDir, ""); 208 if (!sk_exists(grDir.c_str())) { 209 if (!sk_mkdir(grDir.c_str())) { 210 SkDebugf("could not create dir %s\n", grDir.c_str()); 211 return false; 212 } 213 } 214 SkString skDir = make_filepath(0, outSkDir, ""); 215 if (!sk_exists(skDir.c_str())) { 216 if (!sk_mkdir(skDir.c_str())) { 217 SkDebugf("could not create dir %s\n", skDir.c_str()); 218 return false; 219 } 220 } 221 SkString skpDir = make_filepath(0, outSkpDir, ""); 222 if (!sk_exists(skpDir.c_str())) { 223 if (!sk_mkdir(skpDir.c_str())) { 224 SkDebugf("could not create dir %s\n", skpDir.c_str()); 225 return false; 226 } 227 } 228 SkString diffDir = make_filepath(0, outDiffDir, ""); 229 if (!sk_exists(diffDir.c_str())) { 230 if (!sk_mkdir(diffDir.c_str())) { 231 SkDebugf("could not create dir %s\n", diffDir.c_str()); 232 return false; 233 } 234 } 235 SkString statusDir = make_filepath(0, outStatusDir, ""); 236 if (!sk_exists(statusDir.c_str())) { 237 if (!sk_mkdir(statusDir.c_str())) { 238 SkDebugf("could not create dir %s\n", statusDir.c_str()); 239 return false; 240 } 241 } 242 return true; 243 } 244 245 static SkString make_png_name(const char* filename) { 246 SkString pngName = SkString(filename); 247 pngName.remove(pngName.size() - 3, 3); 248 pngName.append("png"); 249 return pngName; 250 } 251 252 typedef GrContextFactory::GLContextType GLContextType; 253 #ifdef SK_BUILD_FOR_WIN 254 static const GLContextType kAngle = GrContextFactory::kANGLE_GLContextType; 255 #else 256 static const GLContextType kNative = GrContextFactory::kNative_GLContextType; 257 #endif 258 259 static int similarBits(const SkBitmap& gr, const SkBitmap& sk) { 260 const int kRowCount = 3; 261 const int kThreshold = 3; 262 int width = SkTMin(gr.width(), sk.width()); 263 if (width < kRowCount) { 264 return true; 265 } 266 int height = SkTMin(gr.height(), sk.height()); 267 if (height < kRowCount) { 268 return true; 269 } 270 int errorTotal = 0; 271 SkTArray<char, true> errorRows; 272 errorRows.push_back_n(width * kRowCount); 273 SkAutoLockPixels autoGr(gr); 274 SkAutoLockPixels autoSk(sk); 275 char* base = &errorRows[0]; 276 for (int y = 0; y < height; ++y) { 277 SkPMColor* grRow = gr.getAddr32(0, y); 278 SkPMColor* skRow = sk.getAddr32(0, y); 279 char* cOut = &errorRows[(y % kRowCount) * width]; 280 for (int x = 0; x < width; ++x) { 281 SkPMColor grColor = grRow[x]; 282 SkPMColor skColor = skRow[x]; 283 int dr = SkGetPackedR32(grColor) - SkGetPackedR32(skColor); 284 int dg = SkGetPackedG32(grColor) - SkGetPackedG32(skColor); 285 int db = SkGetPackedB32(grColor) - SkGetPackedB32(skColor); 286 int error = SkTMax(SkAbs32(dr), SkTMax(SkAbs32(dg), SkAbs32(db))); 287 if ((cOut[x] = error >= kThreshold) && x >= 2 288 && base[x - 2] && base[width + x - 2] && base[width * 2 + x - 2] 289 && base[x - 1] && base[width + x - 1] && base[width * 2 + x - 1] 290 && base[x - 0] && base[width + x - 0] && base[width * 2 + x - 0]) { 291 errorTotal += error; 292 } 293 } 294 } 295 return errorTotal; 296 } 297 298 static bool addError(SkpSkGrThreadState* data) { 299 bool foundSmaller = false; 300 int dCount = data->fFoundCount; 301 int pixelError = data->fResult.fPixelError; 302 if (data->fFoundCount < kMaxFiles) { 303 data->fError[dCount] = pixelError; 304 strcpy(data->fFilesFound[dCount], data->fResult.fFilename); 305 data->fDirsFound[dCount] = data->fResult.fDirNo; 306 ++data->fFoundCount; 307 } else if (pixelError > data->fSmallestError) { 308 int smallest = SK_MaxS32; 309 int smallestIndex = 0; 310 for (int index = 0; index < kMaxFiles; ++index) { 311 if (smallest > data->fError[index]) { 312 smallest = data->fError[index]; 313 smallestIndex = index; 314 } 315 } 316 data->fError[smallestIndex] = pixelError; 317 strcpy(data->fFilesFound[smallestIndex], data->fResult.fFilename); 318 data->fDirsFound[smallestIndex] = data->fResult.fDirNo; 319 data->fSmallestError = SK_MaxS32; 320 for (int index = 0; index < kMaxFiles; ++index) { 321 if (data->fSmallestError > data->fError[index]) { 322 data->fSmallestError = data->fError[index]; 323 } 324 } 325 SkDebugf("*%d*", data->fSmallestError); 326 foundSmaller = true; 327 } 328 return foundSmaller; 329 } 330 331 static SkMSec timePict(SkPicture* pic, SkCanvas* canvas) { 332 canvas->save(); 333 int pWidth = pic->width(); 334 int pHeight = pic->height(); 335 const int maxDimension = 1000; 336 const int slices = 3; 337 int xInterval = SkTMax(pWidth - maxDimension, 0) / (slices - 1); 338 int yInterval = SkTMax(pHeight - maxDimension, 0) / (slices - 1); 339 SkRect rect = {0, 0, SkIntToScalar(SkTMin(maxDimension, pWidth)), 340 SkIntToScalar(SkTMin(maxDimension, pHeight))}; 341 canvas->clipRect(rect); 342 SkMSec start = SkTime::GetMSecs(); 343 for (int x = 0; x < slices; ++x) { 344 for (int y = 0; y < slices; ++y) { 345 pic->draw(canvas); 346 canvas->translate(0, SkIntToScalar(yInterval)); 347 } 348 canvas->translate(SkIntToScalar(xInterval), SkIntToScalar(-yInterval * slices)); 349 } 350 SkMSec end = SkTime::GetMSecs(); 351 canvas->restore(); 352 return end - start; 353 } 354 355 static void drawPict(SkPicture* pic, SkCanvas* canvas, int scale) { 356 canvas->clear(SK_ColorWHITE); 357 if (scale != 1) { 358 canvas->save(); 359 canvas->scale(1.0f / scale, 1.0f / scale); 360 } 361 pic->draw(canvas); 362 if (scale != 1) { 363 canvas->restore(); 364 } 365 } 366 367 static void writePict(const SkBitmap& bitmap, const char* outDir, const char* pngName) { 368 SkString outFile = make_filepath(0, outDir, pngName); 369 if (!SkImageEncoder::EncodeFile(outFile.c_str(), bitmap, 370 SkImageEncoder::kPNG_Type, 100)) { 371 SkDebugf("unable to encode gr %s (width=%d height=%d)br \n", pngName, 372 bitmap.width(), bitmap.height()); 373 } 374 } 375 376 void TestResult::testOne() { 377 SkPicture* pic = NULL; 378 { 379 SkString d; 380 d.printf(" {%d, \"%s\"},", fDirNo, fFilename); 381 SkString path = make_filepath(fDirNo, IN_DIR, fFilename); 382 SkFILEStream stream(path.c_str()); 383 if (!stream.isValid()) { 384 SkDebugf("invalid stream %s\n", path.c_str()); 385 goto finish; 386 } 387 if (fTestStep == kEncodeFiles) { 388 size_t length = stream.getLength(); 389 SkTArray<char, true> bytes; 390 bytes.push_back_n(length); 391 stream.read(&bytes[0], length); 392 stream.rewind(); 393 SkString wPath = make_filepath(0, outSkpDir, fFilename); 394 SkFILEWStream wStream(wPath.c_str()); 395 wStream.write(&bytes[0], length); 396 wStream.flush(); 397 } 398 pic = SkPicture::CreateFromStream(&stream, &SkImageDecoder::DecodeMemory); 399 if (!pic) { 400 SkDebugf("unable to decode %s\n", fFilename); 401 goto finish; 402 } 403 int pWidth = pic->width(); 404 int pHeight = pic->height(); 405 int pLargerWH = SkTMax(pWidth, pHeight); 406 GrContextFactory contextFactory; 407 #ifdef SK_BUILD_FOR_WIN 408 GrContext* context = contextFactory.get(kAngle); 409 #else 410 GrContext* context = contextFactory.get(kNative); 411 #endif 412 if (NULL == context) { 413 SkDebugf("unable to allocate context for %s\n", fFilename); 414 goto finish; 415 } 416 int maxWH = context->getMaxRenderTargetSize(); 417 int scale = 1; 418 while (pLargerWH / scale > maxWH) { 419 scale *= 2; 420 } 421 SkBitmap bitmap; 422 SkIPoint dim; 423 do { 424 dim.fX = (pWidth + scale - 1) / scale; 425 dim.fY = (pHeight + scale - 1) / scale; 426 bool success = bitmap.allocN32Pixels(dim.fX, dim.fY); 427 if (success) { 428 break; 429 } 430 SkDebugf("-%d-", scale); 431 } while ((scale *= 2) < 256); 432 if (scale >= 256) { 433 SkDebugf("unable to allocate bitmap for %s (w=%d h=%d) (sw=%d sh=%d)\n", 434 fFilename, pWidth, pHeight, dim.fX, dim.fY); 435 goto finish; 436 } 437 SkCanvas skCanvas(bitmap); 438 drawPict(pic, &skCanvas, fScaleOversized ? scale : 1); 439 GrTextureDesc desc; 440 desc.fConfig = kSkia8888_GrPixelConfig; 441 desc.fFlags = kRenderTarget_GrTextureFlagBit; 442 desc.fWidth = dim.fX; 443 desc.fHeight = dim.fY; 444 desc.fSampleCnt = 0; 445 SkAutoTUnref<GrTexture> texture(context->createUncachedTexture(desc, NULL, 0)); 446 if (!texture) { 447 SkDebugf("unable to allocate texture for %s (w=%d h=%d)\n", fFilename, 448 dim.fX, dim.fY); 449 goto finish; 450 } 451 SkGpuDevice grDevice(context, texture.get()); 452 SkCanvas grCanvas(&grDevice); 453 drawPict(pic, &grCanvas, fScaleOversized ? scale : 1); 454 455 SkBitmap grBitmap; 456 grBitmap.allocPixels(grCanvas.imageInfo()); 457 grCanvas.readPixels(&grBitmap, 0, 0); 458 459 if (fTestStep == kCompareBits) { 460 fPixelError = similarBits(grBitmap, bitmap); 461 int skTime = timePict(pic, &skCanvas); 462 int grTime = timePict(pic, &grCanvas); 463 fTime = skTime - grTime; 464 } else if (fTestStep == kEncodeFiles) { 465 SkString pngStr = make_png_name(fFilename); 466 const char* pngName = pngStr.c_str(); 467 writePict(grBitmap, outGrDir, pngName); 468 writePict(bitmap, outSkDir, pngName); 469 } 470 } 471 finish: 472 SkDELETE(pic); 473 } 474 475 static SkString makeStatusString(int dirNo) { 476 SkString statName; 477 statName.printf("stats%d.txt", dirNo); 478 SkString statusFile = make_filepath(0, outStatusDir, statName.c_str()); 479 return statusFile; 480 } 481 482 class PreParser { 483 public: 484 PreParser(int dirNo) 485 : fDirNo(dirNo) 486 , fIndex(0) 487 , fStatusPath(makeStatusString(dirNo)) { 488 if (!sk_exists(fStatusPath.c_str())) { 489 return; 490 } 491 SkFILEStream reader; 492 reader.setPath(fStatusPath.c_str()); 493 while (fetch(reader, &fResults.push_back())) 494 ; 495 fResults.pop_back(); 496 } 497 498 bool fetch(SkFILEStream& reader, TestResult* result) { 499 char c; 500 int i = 0; 501 result->init(fDirNo); 502 result->fPixelError = 0; 503 result->fTime = 0; 504 do { 505 bool readOne = reader.read(&c, 1) != 0; 506 if (!readOne) { 507 SkASSERT(i == 0); 508 return false; 509 } 510 if (c == ' ') { 511 result->fFilename[i++] = '\0'; 512 break; 513 } 514 result->fFilename[i++] = c; 515 SkASSERT(i < kMaxLength); 516 } while (true); 517 do { 518 SkAssertResult(reader.read(&c, 1) != 0); 519 if (c == ' ') { 520 break; 521 } 522 SkASSERT(c >= '0' && c <= '9'); 523 result->fPixelError = result->fPixelError * 10 + (c - '0'); 524 } while (true); 525 bool minus = false; 526 do { 527 if (reader.read(&c, 1) == 0) { 528 break; 529 } 530 if (c == '\r' && reader.read(&c, 1) == 0) { 531 break; 532 } 533 if (c == '\n') { 534 break; 535 } 536 if (c == '-') { 537 minus = true; 538 continue; 539 } 540 SkASSERT(c >= '0' && c <= '9'); 541 result->fTime = result->fTime * 10 + (c - '0'); 542 } while (true); 543 if (minus) { 544 result->fTime = -result->fTime; 545 } 546 return true; 547 } 548 549 bool match(const SkString& filename, SkFILEWStream* stream, TestResult* result) { 550 if (fIndex < fResults.count()) { 551 *result = fResults[fIndex++]; 552 SkASSERT(filename.equals(result->fFilename)); 553 SkString outStr(result->status()); 554 stream->write(outStr.c_str(), outStr.size()); 555 stream->flush(); 556 return true; 557 } 558 return false; 559 } 560 561 private: 562 int fDirNo; 563 int fIndex; 564 SkTArray<TestResult, true> fResults; 565 SkString fStatusPath; 566 }; 567 568 static bool initTest() { 569 #if !defined SK_BUILD_FOR_WIN && !defined SK_BUILD_FOR_MAC 570 SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); 571 SK_CONF_SET("images.png.suppressDecoderWarnings", true); 572 #endif 573 return make_out_dirs(); 574 } 575 576 DEF_TEST(SkpSkGr, reporter) { 577 SkTArray<TestResult, true> errors; 578 if (!initTest()) { 579 return; 580 } 581 SkpSkGrThreadState state; 582 state.init(0); 583 int smallCount = 0; 584 for (int dirNo = 1; dirNo <= 100; ++dirNo) { 585 SkString pictDir = make_in_dir_name(dirNo); 586 SkASSERT(pictDir.size()); 587 if (reporter->verbose()) { 588 SkDebugf("dirNo=%d\n", dirNo); 589 } 590 SkOSFile::Iter iter(pictDir.c_str(), "skp"); 591 SkString filename; 592 int testCount = 0; 593 PreParser preParser(dirNo); 594 SkFILEWStream statusStream(makeStatusString(dirNo).c_str()); 595 while (iter.next(&filename)) { 596 for (size_t index = 0; index < skipOverSkGrCount; ++index) { 597 if (skipOverSkGr[index].directory == dirNo 598 && strcmp(filename.c_str(), skipOverSkGr[index].filename) == 0) { 599 goto skipOver; 600 } 601 } 602 if (preParser.match(filename, &statusStream, &state.fResult)) { 603 addError(&state); 604 ++testCount; 605 goto checkEarlyExit; 606 } 607 if (state.fSmallestError > 5000000) { 608 goto breakOut; 609 } 610 { 611 TestResult& result = state.fResult; 612 result.test(dirNo, filename); 613 SkString outStr(result.status()); 614 statusStream.write(outStr.c_str(), outStr.size()); 615 statusStream.flush(); 616 if (1) { 617 SkDebugf("%s", outStr.c_str()); 618 } 619 bool noMatch = addError(&state); 620 if (noMatch) { 621 smallCount = 0; 622 } else if (++smallCount > 10000) { 623 goto breakOut; 624 } 625 } 626 ++testCount; 627 if (reporter->verbose()) { 628 if (testCount % 100 == 0) { 629 SkDebugf("#%d\n", testCount); 630 } 631 } 632 skipOver: 633 reporter->bumpTestCount(); 634 checkEarlyExit: 635 if (1 && testCount == 20) { 636 break; 637 } 638 } 639 } 640 breakOut: 641 if (reporter->verbose()) { 642 for (int index = 0; index < state.fFoundCount; ++index) { 643 SkDebugf("%d %s %d\n", state.fDirsFound[index], state.fFilesFound[index], 644 state.fError[index]); 645 } 646 } 647 for (int index = 0; index < state.fFoundCount; ++index) { 648 TestResult::Test(state.fDirsFound[index], state.fFilesFound[index], kEncodeFiles, 649 reporter->verbose()); 650 if (reporter->verbose()) SkDebugf("+"); 651 } 652 } 653 654 static void bumpCount(skiatest::Reporter* reporter, bool skipping) { 655 if (reporter->verbose()) { 656 static int threadTestCount; 657 sk_atomic_inc(&threadTestCount); 658 if (!skipping && threadTestCount % 100 == 0) { 659 SkDebugf("#%d\n", threadTestCount); 660 } 661 if (skipping && threadTestCount % 10000 == 0) { 662 SkDebugf("#%d\n", threadTestCount); 663 } 664 } 665 } 666 667 static void testSkGrMain(SkpSkGrThreadState* data) { 668 data->fResult.testOne(); 669 bumpCount(data->fReporter, false); 670 data->fReporter->bumpTestCount(); 671 } 672 673 DEF_TEST(SkpSkGrThreaded, reporter) { 674 if (!initTest()) { 675 return; 676 } 677 SkpSkGrThreadedTestRunner testRunner(reporter); 678 for (int dirIndex = 1; dirIndex <= 100; ++dirIndex) { 679 SkString pictDir = make_in_dir_name(dirIndex); 680 if (pictDir.size() == 0) { 681 continue; 682 } 683 SkOSFile::Iter iter(pictDir.c_str(), "skp"); 684 SkString filename; 685 while (iter.next(&filename)) { 686 SkString pngName = make_png_name(filename.c_str()); 687 SkString oldPng = make_filepath(dirIndex, outSkDir, pngName.c_str()); 688 SkString newPng = make_filepath(dirIndex, outGrDir, pngName.c_str()); 689 if (sk_exists(oldPng.c_str()) && sk_exists(newPng.c_str())) { 690 bumpCount(reporter, true); 691 continue; 692 } 693 for (size_t index = 0; index < skipOverSkGrCount; ++index) { 694 if (skipOverSkGr[index].directory == dirIndex 695 && strcmp(filename.c_str(), skipOverSkGr[index].filename) == 0) { 696 bumpCount(reporter, true); 697 goto skipOver; 698 } 699 } 700 *testRunner.fRunnables.append() = SkNEW_ARGS(SkpSkGrThreadedRunnable, 701 (&testSkGrMain, dirIndex, filename.c_str(), &testRunner)); 702 skipOver: 703 ; 704 } 705 } 706 testRunner.render(); 707 SkpSkGrThreadState& max = testRunner.fRunnables[0]->fState; 708 for (int dirIndex = 2; dirIndex <= 100; ++dirIndex) { 709 SkpSkGrThreadState& state = testRunner.fRunnables[dirIndex - 1]->fState; 710 for (int index = 0; index < state.fFoundCount; ++index) { 711 int maxIdx = max.fFoundCount; 712 if (maxIdx < kMaxFiles) { 713 max.fError[maxIdx] = state.fError[index]; 714 strcpy(max.fFilesFound[maxIdx], state.fFilesFound[index]); 715 max.fDirsFound[maxIdx] = state.fDirsFound[index]; 716 ++max.fFoundCount; 717 continue; 718 } 719 for (maxIdx = 0; maxIdx < max.fFoundCount; ++maxIdx) { 720 if (max.fError[maxIdx] < state.fError[index]) { 721 max.fError[maxIdx] = state.fError[index]; 722 strcpy(max.fFilesFound[maxIdx], state.fFilesFound[index]); 723 max.fDirsFound[maxIdx] = state.fDirsFound[index]; 724 break; 725 } 726 } 727 } 728 } 729 TestResult encoder; 730 encoder.fTestStep = kEncodeFiles; 731 for (int index = 0; index < max.fFoundCount; ++index) { 732 encoder.fDirNo = max.fDirsFound[index]; 733 strcpy(encoder.fFilename, max.fFilesFound[index]); 734 encoder.testOne(); 735 SkDebugf("+"); 736 } 737 } 738 739 DEF_TEST(SkpSkGrOneOff, reporter) { 740 if (!initTest()) { 741 return; 742 } 743 int testIndex = 166; 744 int dirIndex = skipOverSkGr[testIndex - 166].directory; 745 SkString pictDir = make_in_dir_name(dirIndex); 746 if (pictDir.size() == 0) { 747 return; 748 } 749 SkString filename(skipOverSkGr[testIndex - 166].filename); 750 TestResult::Test(dirIndex, filename.c_str(), kCompareBits, reporter->verbose()); 751 TestResult::Test(dirIndex, filename.c_str(), kEncodeFiles, reporter->verbose()); 752 } 753