render_pictures_main.cpp revision d17c8656342422447e4c40e4113052ddce4aaf38
1/* 2 * Copyright 2012 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 "CopyTilesRenderer.h" 9#include "SkBitmap.h" 10#include "SkCanvas.h" 11#include "SkDevice.h" 12#include "SkGraphics.h" 13#include "SkImageDecoder.h" 14#include "SkImageEncoder.h" 15#include "SkMath.h" 16#include "SkOSFile.h" 17#include "SkPicture.h" 18#include "SkStream.h" 19#include "SkString.h" 20#include "SkTArray.h" 21#include "PictureRenderer.h" 22#include "picture_utils.h" 23 24static void usage(const char* argv0) { 25 SkDebugf("SkPicture rendering tool\n"); 26 SkDebugf("\n" 27"Usage: \n" 28" %s <input>... \n" 29" [-w <outputDir>]\n" 30" [--mode pow2tile minWidth height | copyTile width height | simple\n" 31" | tile width height]\n" 32" [--pipe]\n" 33" [--bbh bbhType]\n" 34" [--multi count]\n" 35" [--validate [--maxComponentDiff n]]\n" 36" [--writeWholeImage]\n" 37" [--clone n]\n" 38" [--viewport width height][--scale sf]\n" 39" [--device bitmap" 40#if SK_SUPPORT_GPU 41" | gpu" 42#endif 43"]" 44, argv0); 45 SkDebugf("\n\n"); 46 SkDebugf( 47" input: A list of directories and files to use as input. Files are\n" 48" expected to have the .skp extension.\n\n"); 49 SkDebugf( 50" outputDir: directory to write the rendered images.\n\n"); 51 SkDebugf( 52" --mode pow2tile minWidth height | copyTile width height | simple\n" 53" | tile width height | rerecord: Run in the corresponding mode.\n" 54" Default is simple.\n"); 55 SkDebugf( 56" pow2tile minWidth height, Creates tiles with widths\n" 57" that are all a power of two\n" 58" such that they minimize the\n" 59" amount of wasted tile space.\n" 60" minWidth is the minimum width\n" 61" of these tiles and must be a\n" 62" power of two. A simple render\n" 63" is done with these tiles.\n"); 64 SkDebugf( 65" simple, Render using the default rendering method.\n" 66" rerecord, Record the picture as a new skp, with the bitmaps PNG encoded.\n" 67 ); 68 SkDebugf( 69" tile width height, Do a simple render using tiles\n" 70" with the given dimensions.\n" 71" copyTile width height, Draw the picture, then copy it into tiles.\n" 72" Does not support percentages.\n" 73" If the picture is large enough, breaks it into\n" 74" larger tiles (and draws the picture once per\n" 75" larger tile) to avoid creating a large canvas.\n" 76" Add --tiles x y to specify the number of tiles\n" 77" per larger tile in the x and y direction.\n" 78 ); 79 SkDebugf("\n"); 80 SkDebugf( 81" --multi count : Set the number of threads for multi threaded drawing. Must be greater\n" 82" than 1. Only works with tiled rendering.\n" 83" --viewport width height : Set the viewport.\n" 84" --scale sf : Scale drawing by sf.\n" 85" --pipe: Benchmark SkGPipe rendering. Currently incompatible with \"mode\".\n"); 86 SkDebugf( 87" --validate: Verify that the rendered image contains the same pixels as " 88"the picture rendered in simple mode.\n" 89" --maxComponentDiff: maximum diff on a component. Default is 256, " 90"which means we report but we do not generate an error.\n" 91" --writeWholeImage: In tile mode, write the entire rendered image to a " 92"file, instead of an image for each tile.\n"); 93 SkDebugf( 94" --clone n: Clone the picture n times before rendering.\n"); 95 SkDebugf( 96" --bbh bbhType [width height]: Set the bounding box hierarchy type to\n" 97" be used. Accepted values are: none, rtree, grid. Default\n" 98" value is none. Not compatible with --pipe. With value\n" 99" 'grid', width and height must be specified. 'grid' can\n" 100" only be used with modes tile, record, and\n" 101" playbackCreation."); 102 SkDebugf( 103" --device bitmap" 104#if SK_SUPPORT_GPU 105" | gpu" 106#endif 107": Use the corresponding device. Default is bitmap.\n"); 108 SkDebugf( 109" bitmap, Render to a bitmap.\n"); 110#if SK_SUPPORT_GPU 111 SkDebugf( 112" gpu, Render to the GPU.\n"); 113#endif 114} 115 116static void make_output_filepath(SkString* path, const SkString& dir, 117 const SkString& name) { 118 sk_tools::make_filepath(path, dir, name); 119 // Remove ".skp" 120 path->remove(path->size() - 4, 4); 121} 122 123static bool render_picture(const SkString& inputPath, const SkString* outputDir, 124 sk_tools::PictureRenderer& renderer, 125 SkBitmap** out, 126 int clones) { 127 SkString inputFilename; 128 sk_tools::get_basename(&inputFilename, inputPath); 129 130 SkFILEStream inputStream; 131 inputStream.setPath(inputPath.c_str()); 132 if (!inputStream.isValid()) { 133 SkDebugf("Could not open file %s\n", inputPath.c_str()); 134 return false; 135 } 136 137 bool success = false; 138 SkPicture* picture = SkNEW_ARGS(SkPicture, 139 (&inputStream, &success, &SkImageDecoder::DecodeStream)); 140 if (!success) { 141 SkDebugf("Could not read an SkPicture from %s\n", inputPath.c_str()); 142 return false; 143 } 144 145 for (int i = 0; i < clones; ++i) { 146 SkPicture* clone = picture->clone(); 147 SkDELETE(picture); 148 picture = clone; 149 } 150 151 SkDebugf("drawing... [%i %i] %s\n", picture->width(), picture->height(), 152 inputPath.c_str()); 153 154 renderer.init(picture); 155 renderer.setup(); 156 157 SkString* outputPath = NULL; 158 if (NULL != outputDir) { 159 outputPath = SkNEW(SkString); 160 make_output_filepath(outputPath, *outputDir, inputFilename); 161 } 162 163 success = renderer.render(outputPath, out); 164 if (outputPath) { 165 if (!success) { 166 SkDebugf("Could not write to file %s\n", outputPath->c_str()); 167 } 168 SkDELETE(outputPath); 169 } 170 171 renderer.resetState(); 172 173 renderer.end(); 174 175 SkDELETE(picture); 176 return success; 177} 178 179static int MaxDiff(uint32_t v1, uint32_t v2) { 180 return MAX(MAX(abs(SkColorGetA(v1) - SkColorGetA(v2)), abs(SkColorGetR(v1) - SkColorGetR(v2))), 181 MAX(abs(SkColorGetG(v1) - SkColorGetG(v2)), abs(SkColorGetB(v1) - SkColorGetB(v2)))); 182} 183 184static bool render_picture(const SkString& inputPath, const SkString* outputDir, 185 sk_tools::PictureRenderer& renderer, 186 bool validate, int maxComponentDiff, 187 bool writeWholeImage, 188 int clones) { 189 int diffs[256]; 190 memset(diffs, 0x00, sizeof(diffs)); 191 SkBitmap* bitmap = NULL; 192 bool success = render_picture(inputPath, 193 writeWholeImage ? NULL : outputDir, 194 renderer, 195 validate || writeWholeImage ? &bitmap : NULL, clones); 196 197 if (!success || ((validate || writeWholeImage) && bitmap == NULL)) { 198 SkDebugf("Failed to draw the picture.\n"); 199 SkDELETE(bitmap); 200 return false; 201 } 202 203 if (validate) { 204 SkBitmap* referenceBitmap = NULL; 205 sk_tools::SimplePictureRenderer referenceRenderer; 206 success = render_picture(inputPath, NULL, referenceRenderer, 207 &referenceBitmap, 0); 208 209 if (!success || !referenceBitmap) { 210 SkDebugf("Failed to draw the reference picture.\n"); 211 SkDELETE(bitmap); 212 SkDELETE(referenceBitmap); 213 return false; 214 } 215 216 if (success && (bitmap->width() != referenceBitmap->width())) { 217 SkDebugf("Expected image width: %i, actual image width %i.\n", 218 referenceBitmap->width(), bitmap->width()); 219 SkDELETE(bitmap); 220 SkDELETE(referenceBitmap); 221 return false; 222 } 223 if (success && (bitmap->height() != referenceBitmap->height())) { 224 SkDebugf("Expected image height: %i, actual image height %i", 225 referenceBitmap->height(), bitmap->height()); 226 SkDELETE(bitmap); 227 SkDELETE(referenceBitmap); 228 return false; 229 } 230 231 for (int y = 0; success && y < bitmap->height(); y++) { 232 for (int x = 0; success && x < bitmap->width(); x++) { 233 int diff = MaxDiff(*referenceBitmap->getAddr32(x, y), 234 *bitmap->getAddr32(x, y)); 235 SkASSERT(diff >= 0 && diff <= 255); 236 diffs[diff]++; 237 238 if (diff > maxComponentDiff) { 239 SkDebugf("Expected pixel at (%i %i) exceedds maximum " 240 "component diff of %i: 0x%x, actual 0x%x\n", 241 x, y, maxComponentDiff, 242 *referenceBitmap->getAddr32(x, y), 243 *bitmap->getAddr32(x, y)); 244 SkDELETE(bitmap); 245 SkDELETE(referenceBitmap); 246 return false; 247 } 248 } 249 } 250 SkDELETE(referenceBitmap); 251 252 for (int i = 1; i <= 255; ++i) { 253 if(diffs[i] > 0) { 254 SkDebugf("Number of pixels with max diff of %i is %i\n", i, diffs[i]); 255 } 256 } 257 } 258 259 if (writeWholeImage) { 260 sk_tools::force_all_opaque(*bitmap); 261 if (NULL != outputDir && writeWholeImage) { 262 SkString inputFilename; 263 sk_tools::get_basename(&inputFilename, inputPath); 264 SkString outputPath; 265 make_output_filepath(&outputPath, *outputDir, inputFilename); 266 outputPath.append(".png"); 267 if (!SkImageEncoder::EncodeFile(outputPath.c_str(), *bitmap, 268 SkImageEncoder::kPNG_Type, 100)) { 269 SkDebugf("Failed to draw the picture.\n"); 270 success = false; 271 } 272 } 273 } 274 SkDELETE(bitmap); 275 276 return success; 277} 278 279 280static int process_input(const SkString& input, const SkString* outputDir, 281 sk_tools::PictureRenderer& renderer, 282 bool validate, int maxComponentDiff, 283 bool writeWholeImage, int clones) { 284 SkOSFile::Iter iter(input.c_str(), "skp"); 285 SkString inputFilename; 286 int failures = 0; 287 SkDebugf("process_input, %s\n", input.c_str()); 288 if (iter.next(&inputFilename)) { 289 do { 290 SkString inputPath; 291 sk_tools::make_filepath(&inputPath, input, inputFilename); 292 if (!render_picture(inputPath, outputDir, renderer, 293 validate, maxComponentDiff, 294 writeWholeImage, clones)) { 295 ++failures; 296 } 297 } while(iter.next(&inputFilename)); 298 } else if (SkStrEndsWith(input.c_str(), ".skp")) { 299 SkString inputPath(input); 300 if (!render_picture(inputPath, outputDir, renderer, 301 validate, maxComponentDiff, 302 writeWholeImage, clones)) { 303 ++failures; 304 } 305 } else { 306 SkString warning; 307 warning.printf("Warning: skipping %s\n", input.c_str()); 308 SkDebugf(warning.c_str()); 309 } 310 return failures; 311} 312 313static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs, 314 sk_tools::PictureRenderer*& renderer, SkString*& outputDir, 315 bool* validate, int* maxComponentDiff, 316 bool* writeWholeImage, 317 int* clones){ 318 const char* argv0 = argv[0]; 319 char* const* stop = argv + argc; 320 321 sk_tools::PictureRenderer::SkDeviceTypes deviceType = 322 sk_tools::PictureRenderer::kBitmap_DeviceType; 323 324 bool usePipe = false; 325 int numThreads = 1; 326 bool useTiles = false; 327 const char* widthString = NULL; 328 const char* heightString = NULL; 329 int gridWidth = 0; 330 int gridHeight = 0; 331 bool isPowerOf2Mode = false; 332 bool isCopyMode = false; 333 const char* xTilesString = NULL; 334 const char* yTilesString = NULL; 335 const char* mode = NULL; 336 bool gridSupported = false; 337 sk_tools::PictureRenderer::BBoxHierarchyType bbhType = 338 sk_tools::PictureRenderer::kNone_BBoxHierarchyType; 339 *validate = false; 340 *maxComponentDiff = 256; 341 *writeWholeImage = false; 342 *clones = 0; 343 SkISize viewport; 344 viewport.setEmpty(); 345 SkScalar scaleFactor = SK_Scalar1; 346 347 for (++argv; argv < stop; ++argv) { 348 if (0 == strcmp(*argv, "--mode")) { 349 if (renderer != NULL) { 350 renderer->unref(); 351 SkDebugf("Cannot combine modes.\n"); 352 usage(argv0); 353 exit(-1); 354 } 355 356 ++argv; 357 if (argv >= stop) { 358 SkDebugf("Missing mode for --mode\n"); 359 usage(argv0); 360 exit(-1); 361 } 362 363 if (0 == strcmp(*argv, "simple")) { 364 renderer = SkNEW(sk_tools::SimplePictureRenderer); 365 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile")) 366 || 0 == strcmp(*argv, "copyTile")) { 367 useTiles = true; 368 mode = *argv; 369 370 if (0 == strcmp(*argv, "pow2tile")) { 371 isPowerOf2Mode = true; 372 } else if (0 == strcmp(*argv, "copyTile")) { 373 isCopyMode = true; 374 } else { 375 gridSupported = true; 376 } 377 378 ++argv; 379 if (argv >= stop) { 380 SkDebugf("Missing width for --mode %s\n", mode); 381 usage(argv0); 382 exit(-1); 383 } 384 385 widthString = *argv; 386 ++argv; 387 if (argv >= stop) { 388 SkDebugf("Missing height for --mode %s\n", mode); 389 usage(argv0); 390 exit(-1); 391 } 392 heightString = *argv; 393 } else if (0 == strcmp(*argv, "rerecord")) { 394 renderer = SkNEW(sk_tools::RecordPictureRenderer); 395 } else { 396 SkDebugf("%s is not a valid mode for --mode\n", *argv); 397 usage(argv0); 398 exit(-1); 399 } 400 } else if (0 == strcmp(*argv, "--bbh")) { 401 ++argv; 402 if (argv >= stop) { 403 SkDebugf("Missing value for --bbh\n"); 404 usage(argv0); 405 exit(-1); 406 } 407 if (0 == strcmp(*argv, "none")) { 408 bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType; 409 } else if (0 == strcmp(*argv, "rtree")) { 410 bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType; 411 } else if (0 == strcmp(*argv, "grid")) { 412 bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType; 413 ++argv; 414 if (argv >= stop) { 415 SkDebugf("Missing width for --bbh grid\n"); 416 usage(argv0); 417 exit(-1); 418 } 419 gridWidth = atoi(*argv); 420 ++argv; 421 if (argv >= stop) { 422 SkDebugf("Missing height for --bbh grid\n"); 423 usage(argv0); 424 exit(-1); 425 } 426 gridHeight = atoi(*argv); 427 } else { 428 SkDebugf("%s is not a valid value for --bbhType\n", *argv); 429 usage(argv0); 430 exit(-1);; 431 } 432 } else if (0 == strcmp(*argv, "--viewport")) { 433 ++argv; 434 if (argv >= stop) { 435 SkDebugf("Missing width for --viewport\n"); 436 usage(argv0); 437 exit(-1); 438 } 439 viewport.fWidth = atoi(*argv); 440 ++argv; 441 if (argv >= stop) { 442 SkDebugf("Missing height for --viewport\n"); 443 usage(argv0); 444 exit(-1); 445 } 446 viewport.fHeight = atoi(*argv); 447 } else if (0 == strcmp(*argv, "--scale")) { 448 ++argv; 449 if (argv >= stop) { 450 SkDebugf("Missing scaleFactor for --scale\n"); 451 usage(argv0); 452 exit(-1); 453 } 454 scaleFactor = SkDoubleToScalar(atof(*argv)); 455 } else if (0 == strcmp(*argv, "--tiles")) { 456 ++argv; 457 if (argv >= stop) { 458 SkDebugf("Missing x for --tiles\n"); 459 usage(argv0); 460 exit(-1); 461 } 462 xTilesString = *argv; 463 ++argv; 464 if (argv >= stop) { 465 SkDebugf("Missing y for --tiles\n"); 466 usage(argv0); 467 exit(-1); 468 } 469 yTilesString = *argv; 470 } else if (0 == strcmp(*argv, "--pipe")) { 471 usePipe = true; 472 } else if (0 == strcmp(*argv, "--multi")) { 473 ++argv; 474 if (argv >= stop) { 475 SkSafeUnref(renderer); 476 SkDebugf("Missing arg for --multi\n"); 477 usage(argv0); 478 exit(-1); 479 } 480 numThreads = atoi(*argv); 481 if (numThreads < 2) { 482 SkSafeUnref(renderer); 483 SkDebugf("Number of threads must be at least 2.\n"); 484 usage(argv0); 485 exit(-1); 486 } 487 } else if (0 == strcmp(*argv, "--clone")) { 488 ++argv; 489 if (argv >= stop) { 490 SkSafeUnref(renderer); 491 SkDebugf("Missing arg for --clone\n"); 492 usage(argv0); 493 exit(-1); 494 } 495 *clones = atoi(*argv); 496 if (*clones < 0) { 497 SkSafeUnref(renderer); 498 SkDebugf("Number of clones must be at least 0.\n"); 499 usage(argv0); 500 exit(-1); 501 } 502 } else if (0 == strcmp(*argv, "--device")) { 503 ++argv; 504 if (argv >= stop) { 505 SkSafeUnref(renderer); 506 SkDebugf("Missing mode for --device\n"); 507 usage(argv0); 508 exit(-1); 509 } 510 511 if (0 == strcmp(*argv, "bitmap")) { 512 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType; 513 } 514#if SK_SUPPORT_GPU 515 else if (0 == strcmp(*argv, "gpu")) { 516 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType; 517 } 518#endif 519 else { 520 SkSafeUnref(renderer); 521 SkDebugf("%s is not a valid mode for --device\n", *argv); 522 usage(argv0); 523 exit(-1); 524 } 525 526 } else if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) { 527 SkSafeUnref(renderer); 528 usage(argv0); 529 exit(-1); 530 } else if (0 == strcmp(*argv, "-w")) { 531 ++argv; 532 if (argv >= stop) { 533 SkDebugf("Missing output directory for -w\n"); 534 usage(argv0); 535 exit(-1); 536 } 537 outputDir = SkNEW_ARGS(SkString, (*argv)); 538 } else if (0 == strcmp(*argv, "--validate")) { 539 *validate = true; 540 } else if (0 == strcmp(*argv, "--maxComponentDiff")) { 541 if (!*validate) { 542 SkDebugf("--maxComponentDiff must be used only with --validate\n"); 543 usage(argv0); 544 exit(-1); 545 } 546 ++argv; 547 if (argv >= stop) { 548 SkDebugf("Missing arg for --maxComponentDiff\n"); 549 usage(argv0); 550 exit(-1); 551 } 552 *maxComponentDiff = atoi(*argv); 553 if (*maxComponentDiff < 0 || *maxComponentDiff > 256) { 554 SkSafeUnref(renderer); 555 SkDebugf("maxComponentDiff: 0 - 256.\n"); 556 usage(argv0); 557 exit(-1); 558 } 559 } else if (0 == strcmp(*argv, "--writeWholeImage")) { 560 *writeWholeImage = true; 561 } else { 562 inputs->push_back(SkString(*argv)); 563 } 564 } 565 566 if (numThreads > 1 && !useTiles) { 567 SkSafeUnref(renderer); 568 SkDebugf("Multithreaded drawing requires tiled rendering.\n"); 569 usage(argv0); 570 exit(-1); 571 } 572 573 if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) { 574 SkDebugf("--pipe and --bbh cannot be used together\n"); 575 usage(argv0); 576 exit(-1); 577 } 578 579 if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType && 580 !gridSupported) { 581 SkDebugf("'--bbh grid' is not compatible with specified --mode.\n"); 582 usage(argv0); 583 exit(-1); 584 } 585 586 if (useTiles) { 587 SkASSERT(NULL == renderer); 588 sk_tools::TiledPictureRenderer* tiledRenderer; 589 if (isCopyMode) { 590 int x, y; 591 if (xTilesString != NULL) { 592 SkASSERT(yTilesString != NULL); 593 x = atoi(xTilesString); 594 y = atoi(yTilesString); 595 if (x <= 0 || y <= 0) { 596 SkDebugf("--tiles must be given values > 0\n"); 597 usage(argv0); 598 exit(-1); 599 } 600 } else { 601 x = y = 4; 602 } 603 tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y)); 604 } else if (numThreads > 1) { 605 tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads)); 606 } else { 607 tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer); 608 } 609 if (isPowerOf2Mode) { 610 int minWidth = atoi(widthString); 611 if (!SkIsPow2(minWidth) || minWidth < 0) { 612 tiledRenderer->unref(); 613 SkString err; 614 err.printf("-mode %s must be given a width" 615 " value that is a power of two\n", mode); 616 SkDebugf(err.c_str()); 617 usage(argv0); 618 exit(-1); 619 } 620 tiledRenderer->setTileMinPowerOf2Width(minWidth); 621 } else if (sk_tools::is_percentage(widthString)) { 622 if (isCopyMode) { 623 tiledRenderer->unref(); 624 SkString err; 625 err.printf("--mode %s does not support percentages.\n", mode); 626 SkDebugf(err.c_str()); 627 usage(argv0); 628 exit(-1); 629 } 630 tiledRenderer->setTileWidthPercentage(atof(widthString)); 631 if (!(tiledRenderer->getTileWidthPercentage() > 0)) { 632 tiledRenderer->unref(); 633 SkDebugf("--mode %s must be given a width percentage > 0\n", mode); 634 usage(argv0); 635 exit(-1); 636 } 637 } else { 638 tiledRenderer->setTileWidth(atoi(widthString)); 639 if (!(tiledRenderer->getTileWidth() > 0)) { 640 tiledRenderer->unref(); 641 SkDebugf("--mode %s must be given a width > 0\n", mode); 642 usage(argv0); 643 exit(-1); 644 } 645 } 646 647 if (sk_tools::is_percentage(heightString)) { 648 if (isCopyMode) { 649 tiledRenderer->unref(); 650 SkString err; 651 err.printf("--mode %s does not support percentages.\n", mode); 652 SkDebugf(err.c_str()); 653 usage(argv0); 654 exit(-1); 655 } 656 tiledRenderer->setTileHeightPercentage(atof(heightString)); 657 if (!(tiledRenderer->getTileHeightPercentage() > 0)) { 658 tiledRenderer->unref(); 659 SkDebugf("--mode %s must be given a height percentage > 0\n", mode); 660 usage(argv0); 661 exit(-1); 662 } 663 } else { 664 tiledRenderer->setTileHeight(atoi(heightString)); 665 if (!(tiledRenderer->getTileHeight() > 0)) { 666 tiledRenderer->unref(); 667 SkDebugf("--mode %s must be given a height > 0\n", mode); 668 usage(argv0); 669 exit(-1); 670 } 671 } 672 if (numThreads > 1) { 673#if SK_SUPPORT_GPU 674 if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) { 675 tiledRenderer->unref(); 676 SkDebugf("GPU not compatible with multithreaded tiling.\n"); 677 usage(argv0); 678 exit(-1); 679 } 680#endif 681 } 682 renderer = tiledRenderer; 683 if (usePipe) { 684 SkDebugf("Pipe rendering is currently not compatible with tiling.\n" 685 "Turning off pipe.\n"); 686 } 687 } else if (usePipe) { 688 if (renderer != NULL) { 689 renderer->unref(); 690 SkDebugf("Pipe is incompatible with other modes.\n"); 691 usage(argv0); 692 exit(-1); 693 } 694 renderer = SkNEW(sk_tools::PipePictureRenderer); 695 } 696 697 if (inputs->empty()) { 698 SkSafeUnref(renderer); 699 if (NULL != outputDir) { 700 SkDELETE(outputDir); 701 } 702 usage(argv0); 703 exit(-1); 704 } 705 706 if (NULL == renderer) { 707 renderer = SkNEW(sk_tools::SimplePictureRenderer); 708 } 709 710 renderer->setBBoxHierarchyType(bbhType); 711 renderer->setGridSize(gridWidth, gridHeight); 712 renderer->setViewport(viewport); 713 renderer->setScaleFactor(scaleFactor); 714 renderer->setDeviceType(deviceType); 715} 716 717int tool_main(int argc, char** argv); 718int tool_main(int argc, char** argv) { 719 SkAutoGraphics ag; 720 SkTArray<SkString> inputs; 721 sk_tools::PictureRenderer* renderer = NULL; 722 SkString* outputDir = NULL; 723 bool validate = false; 724 int maxComponentDiff = 256; 725 bool writeWholeImage = false; 726 int clones = 0; 727 parse_commandline(argc, argv, &inputs, renderer, outputDir, 728 &validate, &maxComponentDiff, &writeWholeImage, &clones); 729 SkASSERT(renderer); 730 731 int failures = 0; 732 for (int i = 0; i < inputs.count(); i ++) { 733 failures += process_input(inputs[i], outputDir, *renderer, 734 validate, maxComponentDiff, 735 writeWholeImage, clones); 736 } 737 if (failures != 0) { 738 SkDebugf("Failed to render %i pictures.\n", failures); 739 return 1; 740 } 741#if SK_SUPPORT_GPU 742#if GR_CACHE_STATS 743 if (renderer->isUsingGpuDevice()) { 744 GrContext* ctx = renderer->getGrContext(); 745 746 ctx->printCacheStats(); 747 } 748#endif 749#endif 750 if (NULL != outputDir) { 751 SkDELETE(outputDir); 752 } 753 SkDELETE(renderer); 754 return 0; 755} 756 757#if !defined SK_BUILD_FOR_IOS 758int main(int argc, char * const argv[]) { 759 return tool_main(argc, (char**) argv); 760} 761#endif 762