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 "PictureRenderer.h" | 8 #include "PictureRenderer.h" |
9 #include "picture_utils.h" | 9 #include "picture_utils.h" |
10 #include "SamplePipeControllers.h" | 10 #include "SamplePipeControllers.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 return SkScalarLog(x) * log2_conversion_factor; | 41 return SkScalarLog(x) * log2_conversion_factor; |
42 } | 42 } |
43 | 43 |
44 namespace sk_tools { | 44 namespace sk_tools { |
45 | 45 |
46 enum { | 46 enum { |
47 kDefaultTileWidth = 256, | 47 kDefaultTileWidth = 256, |
48 kDefaultTileHeight = 256 | 48 kDefaultTileHeight = 256 |
49 }; | 49 }; |
50 | 50 |
51 void PictureRenderer::init(SkPicture* pict, const SkString* outputDir, | 51 void PictureRenderer::init(SkPicture* pict, const SkString* writePath, const SkS
tring* mismatchPath, |
52 const SkString* inputFilename, bool useChecksumBasedF
ilenames) { | 52 const SkString* inputFilename, bool useChecksumBasedF
ilenames) { |
53 this->CopyString(&fOutputDir, outputDir); | 53 this->CopyString(&fWritePath, writePath); |
| 54 this->CopyString(&fMismatchPath, mismatchPath); |
54 this->CopyString(&fInputFilename, inputFilename); | 55 this->CopyString(&fInputFilename, inputFilename); |
55 fUseChecksumBasedFilenames = useChecksumBasedFilenames; | 56 fUseChecksumBasedFilenames = useChecksumBasedFilenames; |
56 | 57 |
57 SkASSERT(NULL == fPicture); | 58 SkASSERT(NULL == fPicture); |
58 SkASSERT(NULL == fCanvas.get()); | 59 SkASSERT(NULL == fCanvas.get()); |
59 if (NULL != fPicture || NULL != fCanvas.get()) { | 60 if (NULL != fPicture || NULL != fCanvas.get()) { |
60 return; | 61 return; |
61 } | 62 } |
62 | 63 |
63 SkASSERT(pict != NULL); | 64 SkASSERT(pict != NULL); |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 uint32_t PictureRenderer::recordFlags() { | 259 uint32_t PictureRenderer::recordFlags() { |
259 return (kNone_BBoxHierarchyType == fBBoxHierarchyType) | 260 return (kNone_BBoxHierarchyType == fBBoxHierarchyType) |
260 ? 0 | 261 ? 0 |
261 : SkPicture::kUsePathBoundsForClip_RecordingFlag; | 262 : SkPicture::kUsePathBoundsForClip_RecordingFlag; |
262 } | 263 } |
263 | 264 |
264 /** | 265 /** |
265 * Write the canvas to an image file and/or JSON summary. | 266 * Write the canvas to an image file and/or JSON summary. |
266 * | 267 * |
267 * @param canvas Must be non-null. Canvas to be written to a file. | 268 * @param canvas Must be non-null. Canvas to be written to a file. |
268 * @param outputDir If nonempty, write the binary image to a file within this di
rectory; | 269 * @param writePath If nonempty, write the binary image to a file within this di
rectory. |
269 * if empty, don't write out the image at all. | 270 * @param mismatchPath If nonempty, write the binary image to a file within this
directory, |
| 271 * but only if the image does not match expectations. |
270 * @param inputFilename If we are writing out a binary image, use this to build
its filename. | 272 * @param inputFilename If we are writing out a binary image, use this to build
its filename. |
271 * @param jsonSummaryPtr If not null, add image results (checksum) to this summa
ry. | 273 * @param jsonSummaryPtr If not null, add image results (checksum) to this summa
ry. |
272 * @param useChecksumBasedFilenames If true, use checksum-based filenames when w
riting to disk. | 274 * @param useChecksumBasedFilenames If true, use checksum-based filenames when w
riting to disk. |
273 * @param tileNumberPtr If not null, which tile number this image contains. | 275 * @param tileNumberPtr If not null, which tile number this image contains. |
274 * | 276 * |
275 * @return bool True if the operation completed successfully. | 277 * @return bool True if the operation completed successfully. |
276 */ | 278 */ |
277 static bool write(SkCanvas* canvas, const SkString& outputDir, const SkString& i
nputFilename, | 279 static bool write(SkCanvas* canvas, const SkString& writePath, const SkString& m
ismatchPath, |
278 ImageResultsAndExpectations *jsonSummaryPtr, bool useChecksumB
asedFilenames, | 280 const SkString& inputFilename, ImageResultsAndExpectations *js
onSummaryPtr, |
279 const int* tileNumberPtr=NULL) { | 281 bool useChecksumBasedFilenames, const int* tileNumberPtr=NULL)
{ |
280 SkASSERT(canvas != NULL); | 282 SkASSERT(canvas != NULL); |
281 if (NULL == canvas) { | 283 if (NULL == canvas) { |
282 return false; | 284 return false; |
283 } | 285 } |
284 | 286 |
285 SkBitmap bitmap; | 287 SkBitmap bitmap; |
286 SkISize size = canvas->getDeviceSize(); | 288 SkISize size = canvas->getDeviceSize(); |
287 setup_bitmap(&bitmap, size.width(), size.height()); | 289 setup_bitmap(&bitmap, size.width(), size.height()); |
288 | 290 |
289 canvas->readPixels(&bitmap, 0, 0); | 291 canvas->readPixels(&bitmap, 0, 0); |
(...skipping 28 matching lines...) Expand all Loading... |
318 if (outputSubdirPtr) { | 320 if (outputSubdirPtr) { |
319 outputRelativePath.set(outputSubdirPtr); | 321 outputRelativePath.set(outputSubdirPtr); |
320 outputRelativePath.append("/"); // always use "/", even on Windows | 322 outputRelativePath.append("/"); // always use "/", even on Windows |
321 outputRelativePath.append(outputFilename); | 323 outputRelativePath.append(outputFilename); |
322 } else { | 324 } else { |
323 outputRelativePath.set(outputFilename); | 325 outputRelativePath.set(outputFilename); |
324 } | 326 } |
325 | 327 |
326 jsonSummaryPtr->add(inputFilename.c_str(), outputRelativePath.c_str(), | 328 jsonSummaryPtr->add(inputFilename.c_str(), outputRelativePath.c_str(), |
327 *imageDigestPtr, tileNumberPtr); | 329 *imageDigestPtr, tileNumberPtr); |
| 330 if (!mismatchPath.isEmpty() && |
| 331 !jsonSummaryPtr->matchesExpectation(inputFilename.c_str(), *imageDig
estPtr, |
| 332 tileNumberPtr)) { |
| 333 if (!write_bitmap_to_disk(bitmap, mismatchPath, outputSubdirPtr, out
putFilename)) { |
| 334 return false; |
| 335 } |
| 336 } |
328 } | 337 } |
329 | 338 |
330 if (outputDir.isEmpty()) { | 339 if (writePath.isEmpty()) { |
331 return true; | 340 return true; |
| 341 } else { |
| 342 return write_bitmap_to_disk(bitmap, writePath, outputSubdirPtr, outputFi
lename); |
332 } | 343 } |
333 | |
334 SkString dirPath; | |
335 if (outputSubdirPtr) { | |
336 dirPath = SkOSPath::SkPathJoin(outputDir.c_str(), outputSubdirPtr); | |
337 sk_mkdir(dirPath.c_str()); | |
338 } else { | |
339 dirPath.set(outputDir); | |
340 } | |
341 SkString fullPath = SkOSPath::SkPathJoin(dirPath.c_str(), outputFilename.c_s
tr()); | |
342 return SkImageEncoder::EncodeFile(fullPath.c_str(), bitmap, SkImageEncoder::
kPNG_Type, 100); | |
343 } | 344 } |
344 | 345 |
345 ////////////////////////////////////////////////////////////////////////////////
/////////////// | 346 ////////////////////////////////////////////////////////////////////////////////
/////////////// |
346 | 347 |
347 SkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) { | 348 SkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) { |
348 // defer the canvas setup until the render step | 349 // defer the canvas setup until the render step |
349 return NULL; | 350 return NULL; |
350 } | 351 } |
351 | 352 |
352 // the size_t* parameter is deprecated, so we ignore it | 353 // the size_t* parameter is deprecated, so we ignore it |
353 static SkData* encode_bitmap_to_data(size_t*, const SkBitmap& bm) { | 354 static SkData* encode_bitmap_to_data(size_t*, const SkBitmap& bm) { |
354 return SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, 100); | 355 return SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, 100); |
355 } | 356 } |
356 | 357 |
357 bool RecordPictureRenderer::render(SkBitmap** out) { | 358 bool RecordPictureRenderer::render(SkBitmap** out) { |
358 SkAutoTDelete<SkBBHFactory> factory(this->getFactory()); | 359 SkAutoTDelete<SkBBHFactory> factory(this->getFactory()); |
359 SkPictureRecorder recorder; | 360 SkPictureRecorder recorder; |
360 SkCanvas* canvas = recorder.beginRecording(this->getViewWidth(), this->getVi
ewHeight(), | 361 SkCanvas* canvas = recorder.beginRecording(this->getViewWidth(), this->getVi
ewHeight(), |
361 factory.get(), | 362 factory.get(), |
362 this->recordFlags()); | 363 this->recordFlags()); |
363 this->scaleToScaleFactor(canvas); | 364 this->scaleToScaleFactor(canvas); |
364 fPicture->draw(canvas); | 365 fPicture->draw(canvas); |
365 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); | 366 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); |
366 if (!fOutputDir.isEmpty()) { | 367 if (!fWritePath.isEmpty()) { |
367 // Record the new picture as a new SKP with PNG encoded bitmaps. | 368 // Record the new picture as a new SKP with PNG encoded bitmaps. |
368 SkString skpPath = SkOSPath::SkPathJoin(fOutputDir.c_str(), fInputFilena
me.c_str()); | 369 SkString skpPath = SkOSPath::SkPathJoin(fWritePath.c_str(), fInputFilena
me.c_str()); |
369 SkFILEWStream stream(skpPath.c_str()); | 370 SkFILEWStream stream(skpPath.c_str()); |
370 picture->serialize(&stream, &encode_bitmap_to_data); | 371 picture->serialize(&stream, &encode_bitmap_to_data); |
371 return true; | 372 return true; |
372 } | 373 } |
373 return false; | 374 return false; |
374 } | 375 } |
375 | 376 |
376 SkString RecordPictureRenderer::getConfigNameInternal() { | 377 SkString RecordPictureRenderer::getConfigNameInternal() { |
377 return SkString("record"); | 378 return SkString("record"); |
378 } | 379 } |
(...skipping 11 matching lines...) Expand all Loading... |
390 SkGPipeWriter writer; | 391 SkGPipeWriter writer; |
391 SkCanvas* pipeCanvas = writer.startRecording(&pipeController); | 392 SkCanvas* pipeCanvas = writer.startRecording(&pipeController); |
392 pipeCanvas->drawPicture(*fPicture); | 393 pipeCanvas->drawPicture(*fPicture); |
393 writer.endRecording(); | 394 writer.endRecording(); |
394 fCanvas->flush(); | 395 fCanvas->flush(); |
395 if (NULL != out) { | 396 if (NULL != out) { |
396 *out = SkNEW(SkBitmap); | 397 *out = SkNEW(SkBitmap); |
397 setup_bitmap(*out, fPicture->width(), fPicture->height()); | 398 setup_bitmap(*out, fPicture->width(), fPicture->height()); |
398 fCanvas->readPixels(*out, 0, 0); | 399 fCanvas->readPixels(*out, 0, 0); |
399 } | 400 } |
400 return write(fCanvas, fOutputDir, fInputFilename, fJsonSummaryPtr, | 401 return write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummar
yPtr, |
401 fUseChecksumBasedFilenames); | 402 fUseChecksumBasedFilenames); |
402 } | 403 } |
403 | 404 |
404 SkString PipePictureRenderer::getConfigNameInternal() { | 405 SkString PipePictureRenderer::getConfigNameInternal() { |
405 return SkString("pipe"); | 406 return SkString("pipe"); |
406 } | 407 } |
407 | 408 |
408 ////////////////////////////////////////////////////////////////////////////////
/////////////// | 409 ////////////////////////////////////////////////////////////////////////////////
/////////////// |
409 | 410 |
410 void SimplePictureRenderer::init(SkPicture* picture, const SkString* outputDir, | 411 void SimplePictureRenderer::init(SkPicture* picture, const SkString* writePath, |
411 const SkString* inputFilename, bool useChecksum
BasedFilenames) { | 412 const SkString* mismatchPath, const SkString* i
nputFilename, |
412 INHERITED::init(picture, outputDir, inputFilename, useChecksumBasedFilenames
); | 413 bool useChecksumBasedFilenames) { |
| 414 INHERITED::init(picture, writePath, mismatchPath, inputFilename, useChecksum
BasedFilenames); |
413 this->buildBBoxHierarchy(); | 415 this->buildBBoxHierarchy(); |
414 } | 416 } |
415 | 417 |
416 bool SimplePictureRenderer::render(SkBitmap** out) { | 418 bool SimplePictureRenderer::render(SkBitmap** out) { |
417 SkASSERT(fCanvas.get() != NULL); | 419 SkASSERT(fCanvas.get() != NULL); |
418 SkASSERT(NULL != fPicture); | 420 SkASSERT(NULL != fPicture); |
419 if (NULL == fCanvas.get() || NULL == fPicture) { | 421 if (NULL == fCanvas.get() || NULL == fPicture) { |
420 return false; | 422 return false; |
421 } | 423 } |
422 | 424 |
423 fCanvas->drawPicture(*fPicture); | 425 fCanvas->drawPicture(*fPicture); |
424 fCanvas->flush(); | 426 fCanvas->flush(); |
425 if (NULL != out) { | 427 if (NULL != out) { |
426 *out = SkNEW(SkBitmap); | 428 *out = SkNEW(SkBitmap); |
427 setup_bitmap(*out, fPicture->width(), fPicture->height()); | 429 setup_bitmap(*out, fPicture->width(), fPicture->height()); |
428 fCanvas->readPixels(*out, 0, 0); | 430 fCanvas->readPixels(*out, 0, 0); |
429 } | 431 } |
430 return write(fCanvas, fOutputDir, fInputFilename, fJsonSummaryPtr, | 432 return write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummar
yPtr, |
431 fUseChecksumBasedFilenames); | 433 fUseChecksumBasedFilenames); |
432 } | 434 } |
433 | 435 |
434 SkString SimplePictureRenderer::getConfigNameInternal() { | 436 SkString SimplePictureRenderer::getConfigNameInternal() { |
435 return SkString("simple"); | 437 return SkString("simple"); |
436 } | 438 } |
437 | 439 |
438 ////////////////////////////////////////////////////////////////////////////////
/////////////// | 440 ////////////////////////////////////////////////////////////////////////////////
/////////////// |
439 | 441 |
440 TiledPictureRenderer::TiledPictureRenderer() | 442 TiledPictureRenderer::TiledPictureRenderer() |
441 : fTileWidth(kDefaultTileWidth) | 443 : fTileWidth(kDefaultTileWidth) |
442 , fTileHeight(kDefaultTileHeight) | 444 , fTileHeight(kDefaultTileHeight) |
443 , fTileWidthPercentage(0.0) | 445 , fTileWidthPercentage(0.0) |
444 , fTileHeightPercentage(0.0) | 446 , fTileHeightPercentage(0.0) |
445 , fTileMinPowerOf2Width(0) | 447 , fTileMinPowerOf2Width(0) |
446 , fCurrentTileOffset(-1) | 448 , fCurrentTileOffset(-1) |
447 , fTilesX(0) | 449 , fTilesX(0) |
448 , fTilesY(0) { } | 450 , fTilesY(0) { } |
449 | 451 |
450 void TiledPictureRenderer::init(SkPicture* pict, const SkString* outputDir, | 452 void TiledPictureRenderer::init(SkPicture* pict, const SkString* writePath, |
451 const SkString* inputFilename, bool useChecksumB
asedFilenames) { | 453 const SkString* mismatchPath, const SkString* in
putFilename, |
| 454 bool useChecksumBasedFilenames) { |
452 SkASSERT(NULL != pict); | 455 SkASSERT(NULL != pict); |
453 SkASSERT(0 == fTileRects.count()); | 456 SkASSERT(0 == fTileRects.count()); |
454 if (NULL == pict || fTileRects.count() != 0) { | 457 if (NULL == pict || fTileRects.count() != 0) { |
455 return; | 458 return; |
456 } | 459 } |
457 | 460 |
458 // Do not call INHERITED::init(), which would create a (potentially large) c
anvas which is not | 461 // Do not call INHERITED::init(), which would create a (potentially large) c
anvas which is not |
459 // used by bench_pictures. | 462 // used by bench_pictures. |
460 fPicture.reset(pict)->ref(); | 463 fPicture.reset(pict)->ref(); |
461 this->CopyString(&fOutputDir, outputDir); | 464 this->CopyString(&fWritePath, writePath); |
| 465 this->CopyString(&fMismatchPath, mismatchPath); |
462 this->CopyString(&fInputFilename, inputFilename); | 466 this->CopyString(&fInputFilename, inputFilename); |
463 fUseChecksumBasedFilenames = useChecksumBasedFilenames; | 467 fUseChecksumBasedFilenames = useChecksumBasedFilenames; |
464 this->buildBBoxHierarchy(); | 468 this->buildBBoxHierarchy(); |
465 | 469 |
466 if (fTileWidthPercentage > 0) { | 470 if (fTileWidthPercentage > 0) { |
467 fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->wi
dth() / 100)); | 471 fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->wi
dth() / 100)); |
468 } | 472 } |
469 if (fTileHeightPercentage > 0) { | 473 if (fTileHeightPercentage > 0) { |
470 fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->
height() / 100)); | 474 fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->
height() / 100)); |
471 } | 475 } |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
629 | 633 |
630 SkBitmap bitmap; | 634 SkBitmap bitmap; |
631 if (out){ | 635 if (out){ |
632 *out = SkNEW(SkBitmap); | 636 *out = SkNEW(SkBitmap); |
633 setup_bitmap(*out, fPicture->width(), fPicture->height()); | 637 setup_bitmap(*out, fPicture->width(), fPicture->height()); |
634 setup_bitmap(&bitmap, fTileWidth, fTileHeight); | 638 setup_bitmap(&bitmap, fTileWidth, fTileHeight); |
635 } | 639 } |
636 bool success = true; | 640 bool success = true; |
637 for (int i = 0; i < fTileRects.count(); ++i) { | 641 for (int i = 0; i < fTileRects.count(); ++i) { |
638 draw_tile_to_canvas(fCanvas, fTileRects[i], fPicture); | 642 draw_tile_to_canvas(fCanvas, fTileRects[i], fPicture); |
639 success &= write(fCanvas, fOutputDir, fInputFilename, fJsonSummaryPtr, | 643 success &= write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJs
onSummaryPtr, |
640 fUseChecksumBasedFilenames, &i); | 644 fUseChecksumBasedFilenames, &i); |
641 if (NULL != out) { | 645 if (NULL != out) { |
642 if (fCanvas->readPixels(&bitmap, 0, 0)) { | 646 if (fCanvas->readPixels(&bitmap, 0, 0)) { |
643 // Add this tile to the entire bitmap. | 647 // Add this tile to the entire bitmap. |
644 bitmapCopyAtOffset(bitmap, *out, SkScalarFloorToInt(fTileRects[i
].left()), | 648 bitmapCopyAtOffset(bitmap, *out, SkScalarFloorToInt(fTileRects[i
].left()), |
645 SkScalarFloorToInt(fTileRects[i].top())); | 649 SkScalarFloorToInt(fTileRects[i].top())); |
646 } else { | 650 } else { |
647 success = false; | 651 success = false; |
648 } | 652 } |
649 } | 653 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
713 SkGraphics::SetTLSFontCacheLimit(1024 * 1024); | 717 SkGraphics::SetTLSFontCacheLimit(1024 * 1024); |
714 | 718 |
715 SkBitmap bitmap; | 719 SkBitmap bitmap; |
716 if (fBitmap != NULL) { | 720 if (fBitmap != NULL) { |
717 // All tiles are the same size. | 721 // All tiles are the same size. |
718 setup_bitmap(&bitmap, SkScalarFloorToInt(fRects[0].width()), SkScala
rFloorToInt(fRects[0].height())); | 722 setup_bitmap(&bitmap, SkScalarFloorToInt(fRects[0].width()), SkScala
rFloorToInt(fRects[0].height())); |
719 } | 723 } |
720 | 724 |
721 for (int i = fStart; i < fEnd; i++) { | 725 for (int i = fStart; i < fEnd; i++) { |
722 draw_tile_to_canvas(fCanvas, fRects[i], fClone); | 726 draw_tile_to_canvas(fCanvas, fRects[i], fClone); |
723 if (!write(fCanvas, fOutputDir, fInputFilename, fJsonSummaryPtr, | 727 if (!write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJson
SummaryPtr, |
724 fUseChecksumBasedFilenames, &i) | 728 fUseChecksumBasedFilenames, &i) |
725 && fSuccess != NULL) { | 729 && fSuccess != NULL) { |
726 *fSuccess = false; | 730 *fSuccess = false; |
727 // If one tile fails to write to a file, do not continue drawing
the rest. | 731 // If one tile fails to write to a file, do not continue drawing
the rest. |
728 break; | 732 break; |
729 } | 733 } |
730 if (fBitmap != NULL) { | 734 if (fBitmap != NULL) { |
731 if (fCanvas->readPixels(&bitmap, 0, 0)) { | 735 if (fCanvas->readPixels(&bitmap, 0, 0)) { |
732 SkAutoLockPixels alp(*fBitmap); | 736 SkAutoLockPixels alp(*fBitmap); |
733 bitmapCopyAtOffset(bitmap, fBitmap, SkScalarFloorToInt(fRect
s[i].left()), | 737 bitmapCopyAtOffset(bitmap, fBitmap, SkScalarFloorToInt(fRect
s[i].left()), |
734 SkScalarFloorToInt(fRects[i].top())); | 738 SkScalarFloorToInt(fRects[i].top())); |
735 } else { | 739 } else { |
736 *fSuccess = false; | 740 *fSuccess = false; |
737 // If one tile fails to read pixels, do not continue drawing
the rest. | 741 // If one tile fails to read pixels, do not continue drawing
the rest. |
738 break; | 742 break; |
739 } | 743 } |
740 } | 744 } |
741 } | 745 } |
742 fDone->run(); | 746 fDone->run(); |
743 } | 747 } |
744 | 748 |
745 void setPathsAndSuccess(const SkString& outputDir, const SkString& inputFile
name, | 749 void setPathsAndSuccess(const SkString& writePath, const SkString& mismatchP
ath, |
746 bool* success) { | 750 const SkString& inputFilename, bool* success) { |
747 fOutputDir.set(outputDir); | 751 fWritePath.set(writePath); |
| 752 fMismatchPath.set(mismatchPath); |
748 fInputFilename.set(inputFilename); | 753 fInputFilename.set(inputFilename); |
749 fSuccess = success; | 754 fSuccess = success; |
750 } | 755 } |
751 | 756 |
752 void setBitmap(SkBitmap* bitmap) { | 757 void setBitmap(SkBitmap* bitmap) { |
753 fBitmap = bitmap; | 758 fBitmap = bitmap; |
754 } | 759 } |
755 | 760 |
756 private: | 761 private: |
757 // All pointers unowned. | 762 // All pointers unowned. |
758 SkPicture* fClone; // Picture to draw from. Each CloneData has
a unique one which | 763 SkPicture* fClone; // Picture to draw from. Each CloneData has
a unique one which |
759 // is threadsafe. | 764 // is threadsafe. |
760 SkCanvas* fCanvas; // Canvas to draw to. Reused for each tile. | 765 SkCanvas* fCanvas; // Canvas to draw to. Reused for each tile. |
761 SkString fOutputDir; // If not empty, write results into this dir
ectory. | 766 SkString fWritePath; // If not empty, write all results into this
directory. |
| 767 SkString fMismatchPath; // If not empty, write all unexpected res
ults into this dir. |
762 SkString fInputFilename; // Filename of input SkPicture file. | 768 SkString fInputFilename; // Filename of input SkPicture file. |
763 SkTDArray<SkRect>& fRects; // All tiles of the picture. | 769 SkTDArray<SkRect>& fRects; // All tiles of the picture. |
764 const int fStart; // Range of tiles drawn by this thread. | 770 const int fStart; // Range of tiles drawn by this thread. |
765 const int fEnd; | 771 const int fEnd; |
766 bool* fSuccess; // Only meaningful if path is non-null. Shar
ed by all threads, | 772 bool* fSuccess; // Only meaningful if path is non-null. Shar
ed by all threads, |
767 // and only set to false upon failure to wri
te to a PNG. | 773 // and only set to false upon failure to wri
te to a PNG. |
768 SkRunnable* fDone; | 774 SkRunnable* fDone; |
769 SkBitmap* fBitmap; | 775 SkBitmap* fBitmap; |
770 ImageResultsAndExpectations* fJsonSummaryPtr; | 776 ImageResultsAndExpectations* fJsonSummaryPtr; |
771 bool fUseChecksumBasedFilenames; | 777 bool fUseChecksumBasedFilenames; |
772 }; | 778 }; |
773 | 779 |
774 MultiCorePictureRenderer::MultiCorePictureRenderer(int threadCount) | 780 MultiCorePictureRenderer::MultiCorePictureRenderer(int threadCount) |
775 : fNumThreads(threadCount) | 781 : fNumThreads(threadCount) |
776 , fThreadPool(threadCount) | 782 , fThreadPool(threadCount) |
777 , fCountdown(threadCount) { | 783 , fCountdown(threadCount) { |
778 // Only need to create fNumThreads - 1 clones, since one thread will use the
base | 784 // Only need to create fNumThreads - 1 clones, since one thread will use the
base |
779 // picture. | 785 // picture. |
780 fPictureClones = SkNEW_ARRAY(SkPicture, fNumThreads - 1); | 786 fPictureClones = SkNEW_ARRAY(SkPicture, fNumThreads - 1); |
781 fCloneData = SkNEW_ARRAY(CloneData*, fNumThreads); | 787 fCloneData = SkNEW_ARRAY(CloneData*, fNumThreads); |
782 } | 788 } |
783 | 789 |
784 void MultiCorePictureRenderer::init(SkPicture *pict, const SkString* outputDir, | 790 void MultiCorePictureRenderer::init(SkPicture *pict, const SkString* writePath, |
785 const SkString* inputFilename, bool useCheck
sumBasedFilenames) { | 791 const SkString* mismatchPath, const SkString
* inputFilename, |
| 792 bool useChecksumBasedFilenames) { |
786 // Set fPicture and the tiles. | 793 // Set fPicture and the tiles. |
787 this->INHERITED::init(pict, outputDir, inputFilename, useChecksumBasedFilena
mes); | 794 this->INHERITED::init(pict, writePath, mismatchPath, inputFilename, useCheck
sumBasedFilenames); |
788 for (int i = 0; i < fNumThreads; ++i) { | 795 for (int i = 0; i < fNumThreads; ++i) { |
789 *fCanvasPool.append() = this->setupCanvas(this->getTileWidth(), this->ge
tTileHeight()); | 796 *fCanvasPool.append() = this->setupCanvas(this->getTileWidth(), this->ge
tTileHeight()); |
790 } | 797 } |
791 // Only need to create fNumThreads - 1 clones, since one thread will use the
base picture. | 798 // Only need to create fNumThreads - 1 clones, since one thread will use the
base picture. |
792 fPicture->clone(fPictureClones, fNumThreads - 1); | 799 fPicture->clone(fPictureClones, fNumThreads - 1); |
793 // Populate each thread with the appropriate data. | 800 // Populate each thread with the appropriate data. |
794 // Group the tiles into nearly equal size chunks, rounding up so we're sure
to cover them all. | 801 // Group the tiles into nearly equal size chunks, rounding up so we're sure
to cover them all. |
795 const int chunkSize = (fTileRects.count() + fNumThreads - 1) / fNumThreads; | 802 const int chunkSize = (fTileRects.count() + fNumThreads - 1) / fNumThreads; |
796 | 803 |
797 for (int i = 0; i < fNumThreads; i++) { | 804 for (int i = 0; i < fNumThreads; i++) { |
798 SkPicture* pic; | 805 SkPicture* pic; |
799 if (i == fNumThreads-1) { | 806 if (i == fNumThreads-1) { |
800 // The last set will use the original SkPicture. | 807 // The last set will use the original SkPicture. |
801 pic = fPicture; | 808 pic = fPicture; |
802 } else { | 809 } else { |
803 pic = &fPictureClones[i]; | 810 pic = &fPictureClones[i]; |
804 } | 811 } |
805 const int start = i * chunkSize; | 812 const int start = i * chunkSize; |
806 const int end = SkMin32(start + chunkSize, fTileRects.count()); | 813 const int end = SkMin32(start + chunkSize, fTileRects.count()); |
807 fCloneData[i] = SkNEW_ARGS(CloneData, | 814 fCloneData[i] = SkNEW_ARGS(CloneData, |
808 (pic, fCanvasPool[i], fTileRects, start, end,
&fCountdown, | 815 (pic, fCanvasPool[i], fTileRects, start, end,
&fCountdown, |
809 fJsonSummaryPtr, useChecksumBasedFilenames))
; | 816 fJsonSummaryPtr, useChecksumBasedFilenames))
; |
810 } | 817 } |
811 } | 818 } |
812 | 819 |
813 bool MultiCorePictureRenderer::render(SkBitmap** out) { | 820 bool MultiCorePictureRenderer::render(SkBitmap** out) { |
814 bool success = true; | 821 bool success = true; |
815 if (!fOutputDir.isEmpty()) { | 822 if (!fWritePath.isEmpty() || !fMismatchPath.isEmpty()) { |
816 for (int i = 0; i < fNumThreads-1; i++) { | 823 for (int i = 0; i < fNumThreads-1; i++) { |
817 fCloneData[i]->setPathsAndSuccess(fOutputDir, fInputFilename, &succe
ss); | 824 fCloneData[i]->setPathsAndSuccess(fWritePath, fMismatchPath, fInputF
ilename, &success); |
818 } | 825 } |
819 } | 826 } |
820 | 827 |
821 if (NULL != out) { | 828 if (NULL != out) { |
822 *out = SkNEW(SkBitmap); | 829 *out = SkNEW(SkBitmap); |
823 setup_bitmap(*out, fPicture->width(), fPicture->height()); | 830 setup_bitmap(*out, fPicture->width(), fPicture->height()); |
824 for (int i = 0; i < fNumThreads; i++) { | 831 for (int i = 0; i < fNumThreads; i++) { |
825 fCloneData[i]->setBitmap(*out); | 832 fCloneData[i]->setBitmap(*out); |
826 } | 833 } |
827 } else { | 834 } else { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 /////////////////////////////////////////////////////////////////////////////// | 912 /////////////////////////////////////////////////////////////////////////////// |
906 | 913 |
907 class GatherRenderer : public PictureRenderer { | 914 class GatherRenderer : public PictureRenderer { |
908 public: | 915 public: |
909 virtual bool render(SkBitmap** out = NULL) SK_OVERRIDE { | 916 virtual bool render(SkBitmap** out = NULL) SK_OVERRIDE { |
910 SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->width()), | 917 SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->width()), |
911 SkIntToScalar(fPicture->height())); | 918 SkIntToScalar(fPicture->height())); |
912 SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds); | 919 SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds); |
913 SkSafeUnref(data); | 920 SkSafeUnref(data); |
914 | 921 |
915 return (fOutputDir.isEmpty()); // we don't have anything to write | 922 return (fWritePath.isEmpty()); // we don't have anything to write |
916 } | 923 } |
917 | 924 |
918 private: | 925 private: |
919 virtual SkString getConfigNameInternal() SK_OVERRIDE { | 926 virtual SkString getConfigNameInternal() SK_OVERRIDE { |
920 return SkString("gather_pixelrefs"); | 927 return SkString("gather_pixelrefs"); |
921 } | 928 } |
922 }; | 929 }; |
923 | 930 |
924 PictureRenderer* CreateGatherPixelRefsRenderer() { | 931 PictureRenderer* CreateGatherPixelRefsRenderer() { |
925 return SkNEW(GatherRenderer); | 932 return SkNEW(GatherRenderer); |
926 } | 933 } |
927 | 934 |
928 /////////////////////////////////////////////////////////////////////////////// | 935 /////////////////////////////////////////////////////////////////////////////// |
929 | 936 |
930 class PictureCloneRenderer : public PictureRenderer { | 937 class PictureCloneRenderer : public PictureRenderer { |
931 public: | 938 public: |
932 virtual bool render(SkBitmap** out = NULL) SK_OVERRIDE { | 939 virtual bool render(SkBitmap** out = NULL) SK_OVERRIDE { |
933 for (int i = 0; i < 100; ++i) { | 940 for (int i = 0; i < 100; ++i) { |
934 SkPicture* clone = fPicture->clone(); | 941 SkPicture* clone = fPicture->clone(); |
935 SkSafeUnref(clone); | 942 SkSafeUnref(clone); |
936 } | 943 } |
937 | 944 |
938 return (fOutputDir.isEmpty()); // we don't have anything to write | 945 return (fWritePath.isEmpty()); // we don't have anything to write |
939 } | 946 } |
940 | 947 |
941 private: | 948 private: |
942 virtual SkString getConfigNameInternal() SK_OVERRIDE { | 949 virtual SkString getConfigNameInternal() SK_OVERRIDE { |
943 return SkString("picture_clone"); | 950 return SkString("picture_clone"); |
944 } | 951 } |
945 }; | 952 }; |
946 | 953 |
947 PictureRenderer* CreatePictureCloneRenderer() { | 954 PictureRenderer* CreatePictureCloneRenderer() { |
948 return SkNEW(PictureCloneRenderer); | 955 return SkNEW(PictureCloneRenderer); |
949 } | 956 } |
950 | 957 |
951 } // namespace sk_tools | 958 } // namespace sk_tools |
OLD | NEW |