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