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