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