| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "LazyDecodeBitmap.h" | 8 #include "LazyDecodeBitmap.h" |
| 9 #include "CopyTilesRenderer.h" | 9 #include "CopyTilesRenderer.h" |
| 10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 // Flags used by this file, alphabetically: | 25 // Flags used by this file, alphabetically: |
| 26 DEFINE_int32(clone, 0, "Clone the picture n times before rendering."); | 26 DEFINE_int32(clone, 0, "Clone the picture n times before rendering."); |
| 27 DECLARE_bool(deferImageDecoding); | 27 DECLARE_bool(deferImageDecoding); |
| 28 DEFINE_int32(maxComponentDiff, 256, "Maximum diff on a component, 0 - 256. Compo
nents that differ " | 28 DEFINE_int32(maxComponentDiff, 256, "Maximum diff on a component, 0 - 256. Compo
nents that differ " |
| 29 "by more than this amount are considered errors, though all diffs a
re reported. " | 29 "by more than this amount are considered errors, though all diffs a
re reported. " |
| 30 "Requires --validate."); | 30 "Requires --validate."); |
| 31 DECLARE_string(readPath); | 31 DECLARE_string(readPath); |
| 32 DEFINE_bool(writeEncodedImages, false, "Any time the skp contains an encoded ima
ge, write it to a " | 32 DEFINE_bool(writeEncodedImages, false, "Any time the skp contains an encoded ima
ge, write it to a " |
| 33 "file rather than decoding it. Requires writePath to be set. Skips d
rawing the full " | 33 "file rather than decoding it. Requires writePath to be set. Skips d
rawing the full " |
| 34 "skp to a file. Not compatible with deferImageDecoding."); | 34 "skp to a file. Not compatible with deferImageDecoding."); |
| 35 DEFINE_string(writeJsonSummaryPath, "", "File to write a JSON summary of image r
esults to. " |
| 36 "TODO(epoger): Currently, this only works if --writePath is also s
pecified."); |
| 35 DEFINE_string2(writePath, w, "", "Directory to write the rendered images."); | 37 DEFINE_string2(writePath, w, "", "Directory to write the rendered images."); |
| 36 DEFINE_bool(writeWholeImage, false, "In tile mode, write the entire rendered ima
ge to a " | 38 DEFINE_bool(writeWholeImage, false, "In tile mode, write the entire rendered ima
ge to a " |
| 37 "file, instead of an image for each tile."); | 39 "file, instead of an image for each tile."); |
| 38 DEFINE_bool(validate, false, "Verify that the rendered image contains the same p
ixels as " | 40 DEFINE_bool(validate, false, "Verify that the rendered image contains the same p
ixels as " |
| 39 "the picture rendered in simple mode. When used in conjunction with
--bbh, results " | 41 "the picture rendered in simple mode. When used in conjunction with
--bbh, results " |
| 40 "are validated against the picture rendered in the same mode, but wi
thout the bbh."); | 42 "are validated against the picture rendered in the same mode, but wi
thout the bbh."); |
| 41 | 43 |
| 42 DEFINE_bool(bench_record, false, "If true, drop into an infinite loop of recordi
ng the picture."); | 44 DEFINE_bool(bench_record, false, "If true, drop into an infinite loop of recordi
ng the picture."); |
| 43 | 45 |
| 44 static void make_output_filepath(SkString* path, const SkString& dir, | 46 static void make_output_filepath(SkString* path, const SkString& dir, |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 if (!(fileStream.isValid() && fileStream.write(buffer, size))) { | 127 if (!(fileStream.isValid() && fileStream.write(buffer, size))) { |
| 126 SkDebugf("Failed to write encoded data to \"%s\"\n", outPath.c_str()); | 128 SkDebugf("Failed to write encoded data to \"%s\"\n", outPath.c_str()); |
| 127 } | 129 } |
| 128 // Put in a dummy bitmap. | 130 // Put in a dummy bitmap. |
| 129 return SkImageDecoder::DecodeStream(&memStream, bitmap, SkBitmap::kNo_Config
, | 131 return SkImageDecoder::DecodeStream(&memStream, bitmap, SkBitmap::kNo_Config
, |
| 130 SkImageDecoder::kDecodeBounds_Mode); | 132 SkImageDecoder::kDecodeBounds_Mode); |
| 131 } | 133 } |
| 132 | 134 |
| 133 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 135 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 134 | 136 |
| 135 static bool render_picture(const SkString& inputPath, const SkString* outputDir, | 137 /** |
| 136 sk_tools::PictureRenderer& renderer, | 138 * Called only by render_picture(). |
| 137 SkBitmap** out) { | 139 */ |
| 140 static bool render_picture_internal(const SkString& inputPath, const SkString* o
utputDir, |
| 141 sk_tools::PictureRenderer& renderer, |
| 142 SkBitmap** out) { |
| 138 SkString inputFilename; | 143 SkString inputFilename; |
| 139 sk_tools::get_basename(&inputFilename, inputPath); | 144 sk_tools::get_basename(&inputFilename, inputPath); |
| 140 | 145 |
| 141 SkFILEStream inputStream; | 146 SkFILEStream inputStream; |
| 142 inputStream.setPath(inputPath.c_str()); | 147 inputStream.setPath(inputPath.c_str()); |
| 143 if (!inputStream.isValid()) { | 148 if (!inputStream.isValid()) { |
| 144 SkDebugf("Could not open file %s\n", inputPath.c_str()); | 149 SkDebugf("Could not open file %s\n", inputPath.c_str()); |
| 145 return false; | 150 return false; |
| 146 } | 151 } |
| 147 | 152 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 fRenderer->setBBoxHierarchyType(fSavedBbhType); | 239 fRenderer->setBBoxHierarchyType(fSavedBbhType); |
| 235 } | 240 } |
| 236 } | 241 } |
| 237 | 242 |
| 238 private: | 243 private: |
| 239 sk_tools::PictureRenderer* fRenderer; | 244 sk_tools::PictureRenderer* fRenderer; |
| 240 sk_tools::PictureRenderer::BBoxHierarchyType fSavedBbhType; | 245 sk_tools::PictureRenderer::BBoxHierarchyType fSavedBbhType; |
| 241 }; | 246 }; |
| 242 } | 247 } |
| 243 | 248 |
| 249 /** |
| 250 * Render the SKP file(s) within inputPath, writing their bitmap images into out
putDir. |
| 251 * |
| 252 * @param inputPath path to an individual SKP file, or a directory of SKP files |
| 253 * @param outputDir if not NULL, write the image(s) generated into this director
y |
| 254 * @param renderer PictureRenderer to use to render the SKPs |
| 255 * @param jsonSummaryPtr if not NULL, add the image(s) generated to this summary |
| 256 */ |
| 244 static bool render_picture(const SkString& inputPath, const SkString* outputDir, | 257 static bool render_picture(const SkString& inputPath, const SkString* outputDir, |
| 245 sk_tools::PictureRenderer& renderer) { | 258 sk_tools::PictureRenderer& renderer, |
| 259 sk_tools::ImageResultsSummary *jsonSummaryPtr) { |
| 246 int diffs[256] = {0}; | 260 int diffs[256] = {0}; |
| 247 SkBitmap* bitmap = NULL; | 261 SkBitmap* bitmap = NULL; |
| 248 bool success = render_picture(inputPath, | 262 renderer.setJsonSummaryPtr(jsonSummaryPtr); |
| 263 bool success = render_picture_internal(inputPath, |
| 249 FLAGS_writeWholeImage ? NULL : outputDir, | 264 FLAGS_writeWholeImage ? NULL : outputDir, |
| 250 renderer, | 265 renderer, |
| 251 FLAGS_validate || FLAGS_writeWholeImage ? &bitmap : NULL); | 266 FLAGS_validate || FLAGS_writeWholeImage ? &bitmap : NULL); |
| 252 | 267 |
| 253 if (!success || ((FLAGS_validate || FLAGS_writeWholeImage) && bitmap == NULL
)) { | 268 if (!success || ((FLAGS_validate || FLAGS_writeWholeImage) && bitmap == NULL
)) { |
| 254 SkDebugf("Failed to draw the picture.\n"); | 269 SkDebugf("Failed to draw the picture.\n"); |
| 255 SkDELETE(bitmap); | 270 SkDELETE(bitmap); |
| 256 return false; | 271 return false; |
| 257 } | 272 } |
| 258 | 273 |
| 259 if (FLAGS_validate) { | 274 if (FLAGS_validate) { |
| 260 SkBitmap* referenceBitmap = NULL; | 275 SkBitmap* referenceBitmap = NULL; |
| 261 sk_tools::PictureRenderer* referenceRenderer; | 276 sk_tools::PictureRenderer* referenceRenderer; |
| 262 // If the renderer uses a BBoxHierarchy, then the reference renderer | 277 // If the renderer uses a BBoxHierarchy, then the reference renderer |
| 263 // will be the same renderer, without the bbh. | 278 // will be the same renderer, without the bbh. |
| 264 AutoRestoreBbhType arbbh; | 279 AutoRestoreBbhType arbbh; |
| 265 if (sk_tools::PictureRenderer::kNone_BBoxHierarchyType != | 280 if (sk_tools::PictureRenderer::kNone_BBoxHierarchyType != |
| 266 renderer.getBBoxHierarchyType()) { | 281 renderer.getBBoxHierarchyType()) { |
| 267 referenceRenderer = &renderer; | 282 referenceRenderer = &renderer; |
| 268 referenceRenderer->ref(); // to match auto unref below | 283 referenceRenderer->ref(); // to match auto unref below |
| 269 arbbh.set(referenceRenderer, sk_tools::PictureRenderer::kNone_BBoxHi
erarchyType); | 284 arbbh.set(referenceRenderer, sk_tools::PictureRenderer::kNone_BBoxHi
erarchyType); |
| 270 } else { | 285 } else { |
| 271 referenceRenderer = SkNEW(sk_tools::SimplePictureRenderer); | 286 referenceRenderer = SkNEW(sk_tools::SimplePictureRenderer); |
| 272 } | 287 } |
| 273 SkAutoTUnref<sk_tools::PictureRenderer> aurReferenceRenderer(referenceRe
nderer); | 288 SkAutoTUnref<sk_tools::PictureRenderer> aurReferenceRenderer(referenceRe
nderer); |
| 274 | 289 |
| 275 success = render_picture(inputPath, NULL, *referenceRenderer, | 290 success = render_picture_internal(inputPath, NULL, *referenceRenderer, |
| 276 &referenceBitmap); | 291 &referenceBitmap); |
| 277 | 292 |
| 278 if (!success || NULL == referenceBitmap || NULL == referenceBitmap->getP
ixels()) { | 293 if (!success || NULL == referenceBitmap || NULL == referenceBitmap->getP
ixels()) { |
| 279 SkDebugf("Failed to draw the reference picture.\n"); | 294 SkDebugf("Failed to draw the reference picture.\n"); |
| 280 SkDELETE(bitmap); | 295 SkDELETE(bitmap); |
| 281 SkDELETE(referenceBitmap); | 296 SkDELETE(referenceBitmap); |
| 282 return false; | 297 return false; |
| 283 } | 298 } |
| 284 | 299 |
| 285 if (success && (bitmap->width() != referenceBitmap->width())) { | 300 if (success && (bitmap->width() != referenceBitmap->width())) { |
| 286 SkDebugf("Expected image width: %i, actual image width %i.\n", | 301 SkDebugf("Expected image width: %i, actual image width %i.\n", |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 | 335 |
| 321 for (int i = 1; i <= 255; ++i) { | 336 for (int i = 1; i <= 255; ++i) { |
| 322 if(diffs[i] > 0) { | 337 if(diffs[i] > 0) { |
| 323 SkDebugf("Number of pixels with max diff of %i is %i\n", i, diff
s[i]); | 338 SkDebugf("Number of pixels with max diff of %i is %i\n", i, diff
s[i]); |
| 324 } | 339 } |
| 325 } | 340 } |
| 326 } | 341 } |
| 327 | 342 |
| 328 if (FLAGS_writeWholeImage) { | 343 if (FLAGS_writeWholeImage) { |
| 329 sk_tools::force_all_opaque(*bitmap); | 344 sk_tools::force_all_opaque(*bitmap); |
| 330 if (NULL != outputDir && FLAGS_writeWholeImage) { | 345 |
| 346 if (NULL != jsonSummaryPtr) { |
| 347 // EPOGER: This is a hacky way of constructing the filename associat
ed with the |
| 348 // image checksum; we basically are repeating the logic of make_outp
ut_filepath() |
| 349 // and code below here, within here. |
| 350 // It would be better for the filename (without outputDir) to be pas
sed in here, |
| 351 // and used both for the checksum file and writing into outputDir. |
| 352 // |
| 353 // EPOGER: what about including the config type within hashFilename?
That way, |
| 354 // we could combine results of different config types without confli
cting filenames. |
| 355 SkString hashFilename; |
| 356 sk_tools::get_basename(&hashFilename, inputPath); |
| 357 hashFilename.remove(hashFilename.size() - 4, 4); // Remove ".skp" |
| 358 hashFilename.append(".png"); |
| 359 jsonSummaryPtr->add(hashFilename.c_str(), *bitmap); |
| 360 } |
| 361 |
| 362 if (NULL != outputDir) { |
| 331 SkString inputFilename; | 363 SkString inputFilename; |
| 332 sk_tools::get_basename(&inputFilename, inputPath); | 364 sk_tools::get_basename(&inputFilename, inputPath); |
| 333 SkString outputPath; | 365 SkString outputPath; |
| 334 make_output_filepath(&outputPath, *outputDir, inputFilename); | 366 make_output_filepath(&outputPath, *outputDir, inputFilename); |
| 335 outputPath.append(".png"); | 367 outputPath.append(".png"); |
| 336 if (!SkImageEncoder::EncodeFile(outputPath.c_str(), *bitmap, | 368 if (!SkImageEncoder::EncodeFile(outputPath.c_str(), *bitmap, |
| 337 SkImageEncoder::kPNG_Type, 100)) { | 369 SkImageEncoder::kPNG_Type, 100)) { |
| 338 SkDebugf("Failed to draw the picture.\n"); | 370 SkDebugf("Failed to draw the picture.\n"); |
| 339 success = false; | 371 success = false; |
| 340 } | 372 } |
| 341 } | 373 } |
| 342 } | 374 } |
| 343 SkDELETE(bitmap); | 375 SkDELETE(bitmap); |
| 344 | 376 |
| 345 return success; | 377 return success; |
| 346 } | 378 } |
| 347 | 379 |
| 348 | 380 |
| 349 static int process_input(const char* input, const SkString* outputDir, | 381 static int process_input(const char* input, const SkString* outputDir, |
| 350 sk_tools::PictureRenderer& renderer) { | 382 sk_tools::PictureRenderer& renderer, |
| 383 sk_tools::ImageResultsSummary *jsonSummaryPtr) { |
| 351 SkOSFile::Iter iter(input, "skp"); | 384 SkOSFile::Iter iter(input, "skp"); |
| 352 SkString inputFilename; | 385 SkString inputFilename; |
| 353 int failures = 0; | 386 int failures = 0; |
| 354 SkDebugf("process_input, %s\n", input); | 387 SkDebugf("process_input, %s\n", input); |
| 355 if (iter.next(&inputFilename)) { | 388 if (iter.next(&inputFilename)) { |
| 356 do { | 389 do { |
| 357 SkString inputPath; | 390 SkString inputPath; |
| 358 SkString inputAsSkString(input); | 391 SkString inputAsSkString(input); |
| 359 sk_tools::make_filepath(&inputPath, inputAsSkString, inputFilename); | 392 sk_tools::make_filepath(&inputPath, inputAsSkString, inputFilename); |
| 360 if (!render_picture(inputPath, outputDir, renderer)) { | 393 if (!render_picture(inputPath, outputDir, renderer, jsonSummaryPtr))
{ |
| 361 ++failures; | 394 ++failures; |
| 362 } | 395 } |
| 363 } while(iter.next(&inputFilename)); | 396 } while(iter.next(&inputFilename)); |
| 364 } else if (SkStrEndsWith(input, ".skp")) { | 397 } else if (SkStrEndsWith(input, ".skp")) { |
| 365 SkString inputPath(input); | 398 SkString inputPath(input); |
| 366 if (!render_picture(inputPath, outputDir, renderer)) { | 399 if (!render_picture(inputPath, outputDir, renderer, jsonSummaryPtr)) { |
| 367 ++failures; | 400 ++failures; |
| 368 } | 401 } |
| 369 } else { | 402 } else { |
| 370 SkString warning; | 403 SkString warning; |
| 371 warning.printf("Warning: skipping %s\n", input); | 404 warning.printf("Warning: skipping %s\n", input); |
| 372 SkDebugf(warning.c_str()); | 405 SkDebugf(warning.c_str()); |
| 373 } | 406 } |
| 374 return failures; | 407 return failures; |
| 375 } | 408 } |
| 376 | 409 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 if (renderer.get() == NULL) { | 453 if (renderer.get() == NULL) { |
| 421 exit(-1); | 454 exit(-1); |
| 422 } | 455 } |
| 423 | 456 |
| 424 SkAutoGraphics ag; | 457 SkAutoGraphics ag; |
| 425 | 458 |
| 426 SkString outputDir; | 459 SkString outputDir; |
| 427 if (FLAGS_writePath.count() == 1) { | 460 if (FLAGS_writePath.count() == 1) { |
| 428 outputDir.set(FLAGS_writePath[0]); | 461 outputDir.set(FLAGS_writePath[0]); |
| 429 } | 462 } |
| 463 sk_tools::ImageResultsSummary jsonSummary; |
| 464 sk_tools::ImageResultsSummary* jsonSummaryPtr = NULL; |
| 465 if (FLAGS_writeJsonSummaryPath.count() == 1) { |
| 466 jsonSummaryPtr = &jsonSummary; |
| 467 } |
| 430 | 468 |
| 431 int failures = 0; | 469 int failures = 0; |
| 432 for (int i = 0; i < FLAGS_readPath.count(); i ++) { | 470 for (int i = 0; i < FLAGS_readPath.count(); i ++) { |
| 433 failures += process_input(FLAGS_readPath[i], &outputDir, *renderer.get()
); | 471 failures += process_input(FLAGS_readPath[i], &outputDir, *renderer.get()
, jsonSummaryPtr); |
| 434 } | 472 } |
| 435 if (failures != 0) { | 473 if (failures != 0) { |
| 436 SkDebugf("Failed to render %i pictures.\n", failures); | 474 SkDebugf("Failed to render %i pictures.\n", failures); |
| 437 return 1; | 475 return 1; |
| 438 } | 476 } |
| 439 #if SK_SUPPORT_GPU | 477 #if SK_SUPPORT_GPU |
| 440 #if GR_CACHE_STATS | 478 #if GR_CACHE_STATS |
| 441 if (renderer->isUsingGpuDevice()) { | 479 if (renderer->isUsingGpuDevice()) { |
| 442 GrContext* ctx = renderer->getGrContext(); | 480 GrContext* ctx = renderer->getGrContext(); |
| 443 ctx->printCacheStats(); | 481 ctx->printCacheStats(); |
| 444 #ifdef SK_DEVELOPER | 482 #ifdef SK_DEVELOPER |
| 445 ctx->dumpFontCache(); | 483 ctx->dumpFontCache(); |
| 446 #endif | 484 #endif |
| 447 } | 485 } |
| 448 #endif | 486 #endif |
| 449 #endif | 487 #endif |
| 488 if (FLAGS_writeJsonSummaryPath.count() == 1) { |
| 489 jsonSummary.writeToFile(FLAGS_writeJsonSummaryPath[0]); |
| 490 } |
| 450 return 0; | 491 return 0; |
| 451 } | 492 } |
| 452 | 493 |
| 453 #if !defined SK_BUILD_FOR_IOS | 494 #if !defined SK_BUILD_FOR_IOS |
| 454 int main(int argc, char * const argv[]) { | 495 int main(int argc, char * const argv[]) { |
| 455 return tool_main(argc, (char**) argv); | 496 return tool_main(argc, (char**) argv); |
| 456 } | 497 } |
| 457 #endif | 498 #endif |
| OLD | NEW |