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