Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(596)

Side by Side Diff: tools/PictureRenderer.cpp

Issue 202983003: add --writeChecksumBasedFilenames flag to render_pictures (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: pass SkString pointers to init Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/PictureRenderer.h ('k') | tools/bbh_shootout.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 }; 51 };
52 52
53 /* TODO(epoger): These constants are already maintained in 2 other places: 53 /* TODO(epoger): These constants are already maintained in 2 other places:
54 * gm/gm_json.py and gm/gm_expectations.cpp. We shouldn't add yet a third place . 54 * gm/gm_json.py and gm/gm_expectations.cpp. We shouldn't add yet a third place .
55 * Figure out a way to share the definitions instead. 55 * Figure out a way to share the definitions instead.
56 */ 56 */
57 const static char kJsonKey_ActualResults[] = "actual-results"; 57 const static char kJsonKey_ActualResults[] = "actual-results";
58 const static char kJsonKey_ActualResults_NoComparison[] = "no-comparison"; 58 const static char kJsonKey_ActualResults_NoComparison[] = "no-comparison";
59 const static char kJsonKey_Hashtype_Bitmap_64bitMD5[] = "bitmap-64bitMD5"; 59 const static char kJsonKey_Hashtype_Bitmap_64bitMD5[] = "bitmap-64bitMD5";
60 60
61 void ImageResultsSummary::add(const char *testName, const SkBitmap& bitmap) { 61 void ImageResultsSummary::add(const char *testName, uint64_t hash) {
62 uint64_t hash;
63 SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash));
64 Json::Value jsonTypeValuePair; 62 Json::Value jsonTypeValuePair;
65 jsonTypeValuePair.append(Json::Value(kJsonKey_Hashtype_Bitmap_64bitMD5)); 63 jsonTypeValuePair.append(Json::Value(kJsonKey_Hashtype_Bitmap_64bitMD5));
66 jsonTypeValuePair.append(Json::UInt64(hash)); 64 jsonTypeValuePair.append(Json::UInt64(hash));
67 fActualResultsNoComparison[testName] = jsonTypeValuePair; 65 fActualResultsNoComparison[testName] = jsonTypeValuePair;
68 } 66 }
69 67
68 void ImageResultsSummary::add(const char *testName, const SkBitmap& bitmap) {
69 uint64_t hash;
70 SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash));
71 this->add(testName, hash);
72 }
73
70 void ImageResultsSummary::writeToFile(const char *filename) { 74 void ImageResultsSummary::writeToFile(const char *filename) {
71 Json::Value actualResults; 75 Json::Value actualResults;
72 actualResults[kJsonKey_ActualResults_NoComparison] = fActualResultsNoCompari son; 76 actualResults[kJsonKey_ActualResults_NoComparison] = fActualResultsNoCompari son;
73 Json::Value root; 77 Json::Value root;
74 root[kJsonKey_ActualResults] = actualResults; 78 root[kJsonKey_ActualResults] = actualResults;
75 std::string jsonStdString = root.toStyledString(); 79 std::string jsonStdString = root.toStyledString();
76 SkFILEWStream stream(filename); 80 SkFILEWStream stream(filename);
77 stream.write(jsonStdString.c_str(), jsonStdString.length()); 81 stream.write(jsonStdString.c_str(), jsonStdString.length());
78 } 82 }
79 83
80 void PictureRenderer::init(SkPicture* pict) { 84 void PictureRenderer::init(SkPicture* pict, const SkString* outputDir,
85 const SkString* inputFilename, bool useChecksumBasedF ilenames) {
86 this->CopyString(&fOutputDir, outputDir);
87 this->CopyString(&fInputFilename, inputFilename);
88 fUseChecksumBasedFilenames = useChecksumBasedFilenames;
89
81 SkASSERT(NULL == fPicture); 90 SkASSERT(NULL == fPicture);
82 SkASSERT(NULL == fCanvas.get()); 91 SkASSERT(NULL == fCanvas.get());
83 if (fPicture != NULL || NULL != fCanvas.get()) { 92 if (fPicture != NULL || NULL != fCanvas.get()) {
84 return; 93 return;
85 } 94 }
86 95
87 SkASSERT(pict != NULL); 96 SkASSERT(pict != NULL);
88 if (NULL == pict) { 97 if (NULL == pict) {
89 return; 98 return;
90 } 99 }
91 100
92 fPicture = pict; 101 fPicture = pict;
93 fPicture->ref(); 102 fPicture->ref();
94 fCanvas.reset(this->setupCanvas()); 103 fCanvas.reset(this->setupCanvas());
95 } 104 }
96 105
106 void PictureRenderer::CopyString(SkString* dest, const SkString* src) {
107 if (NULL != src) {
108 dest->set(*src);
109 } else {
110 dest->reset();
111 }
112 }
113
97 class FlagsDrawFilter : public SkDrawFilter { 114 class FlagsDrawFilter : public SkDrawFilter {
98 public: 115 public:
99 FlagsDrawFilter(PictureRenderer::DrawFilterFlags* flags) : 116 FlagsDrawFilter(PictureRenderer::DrawFilterFlags* flags) :
100 fFlags(flags) {} 117 fFlags(flags) {}
101 118
102 virtual bool filter(SkPaint* paint, Type t) { 119 virtual bool filter(SkPaint* paint, Type t) {
103 paint->setFlags(paint->getFlags() & ~fFlags[t] & SkPaint::kAllFlags); 120 paint->setFlags(paint->getFlags() & ~fFlags[t] & SkPaint::kAllFlags);
104 if (PictureRenderer::kMaskFilter_DrawFilterFlag & fFlags[t]) { 121 if (PictureRenderer::kMaskFilter_DrawFilterFlag & fFlags[t]) {
105 SkMaskFilter* maskFilter = paint->getMaskFilter(); 122 SkMaskFilter* maskFilter = paint->getMaskFilter();
106 if (NULL != maskFilter) { 123 if (NULL != maskFilter) {
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 } 291 }
275 292
276 uint32_t PictureRenderer::recordFlags() { 293 uint32_t PictureRenderer::recordFlags() {
277 return ((kNone_BBoxHierarchyType == fBBoxHierarchyType) ? 0 : 294 return ((kNone_BBoxHierarchyType == fBBoxHierarchyType) ? 0 :
278 SkPicture::kOptimizeForClippedPlayback_RecordingFlag) | 295 SkPicture::kOptimizeForClippedPlayback_RecordingFlag) |
279 SkPicture::kUsePathBoundsForClip_RecordingFlag; 296 SkPicture::kUsePathBoundsForClip_RecordingFlag;
280 } 297 }
281 298
282 /** 299 /**
283 * Write the canvas to the specified path. 300 * Write the canvas to the specified path.
301 *
284 * @param canvas Must be non-null. Canvas to be written to a file. 302 * @param canvas Must be non-null. Canvas to be written to a file.
285 * @param path Path for the file to be written. Should have no extension; write( ) will append 303 * @param outputDir If nonempty, write the binary image to a file within this di rectory.
286 * an appropriate one. Passed in by value so it can be modified. 304 * @param inputFilename If we are writing out a binary image, use this to build its filename.
287 * @param jsonSummaryPtr If not null, add image results to this summary. 305 * @param jsonSummaryPtr If not null, add image results to this summary.
306 * @param useChecksumBasedFilenames If true, use checksum-based filenames when w riting to disk.
307 * @param numberToAppend If not null, append this number to the filename.
288 * @return bool True if the Canvas is written to a file. 308 * @return bool True if the Canvas is written to a file.
289 * 309 *
290 * TODO(epoger): Right now, all canvases must pass through this function in orde r to be appended 310 * TODO(epoger): Right now, all canvases must pass through this function in orde r to be appended
291 * to the ImageResultsSummary. We need some way to add bitmaps to the ImageResu ltsSummary 311 * to the ImageResultsSummary. We need some way to add bitmaps to the ImageResu ltsSummary
292 * even if --writePath has not been specified (and thus this function is not cal led). 312 * even if --writePath has not been specified (and thus this function is not cal led).
293 * 313 *
294 * One fix would be to pass in these path elements separately, and allow this fu nction to be 314 * One fix would be to pass in these path elements separately, and allow this fu nction to be
295 * called even if --writePath was not specified... 315 * called even if --writePath was not specified...
296 * const char *outputDir // NULL if we don't want to write image files to dis k 316 * const char *outputDir // NULL if we don't want to write image files to dis k
297 * const char *filename // name we use within JSON summary, and as the filen ame within outputDir 317 * const char *filename // name we use within JSON summary, and as the filen ame within outputDir
318 *
319 * UPDATE: Now that outputDir and inputFilename are passed separately, we should be able to do that.
298 */ 320 */
299 static bool write(SkCanvas* canvas, const SkString* path, ImageResultsSummary *j sonSummaryPtr) { 321 static bool write(SkCanvas* canvas, const SkString& outputDir, const SkString& i nputFilename,
322 ImageResultsSummary *jsonSummaryPtr, bool useChecksumBasedFile names,
323 const int* numberToAppend=NULL) {
300 SkASSERT(canvas != NULL); 324 SkASSERT(canvas != NULL);
301 if (NULL == canvas) { 325 if (NULL == canvas) {
302 return false; 326 return false;
303 } 327 }
304 328
305 SkASSERT(path != NULL); // TODO(epoger): we want to remove this constraint, as noted above
306 SkString fullPathname(*path);
307 fullPathname.append(".png");
308
309 SkBitmap bitmap; 329 SkBitmap bitmap;
310 SkISize size = canvas->getDeviceSize(); 330 SkISize size = canvas->getDeviceSize();
311 sk_tools::setup_bitmap(&bitmap, size.width(), size.height()); 331 sk_tools::setup_bitmap(&bitmap, size.width(), size.height());
312 332
333 // Make sure we only compute the bitmap hash once (at most).
334 uint64_t hash;
335 bool generatedHash = false;
336
313 canvas->readPixels(&bitmap, 0, 0); 337 canvas->readPixels(&bitmap, 0, 0);
314 sk_tools::force_all_opaque(bitmap); 338 sk_tools::force_all_opaque(bitmap);
315 339
340 SkString outputFilename(inputFilename);
341 outputFilename.remove(outputFilename.size() - 4, 4);
342 if (NULL != numberToAppend) {
343 outputFilename.appendf("%i", *numberToAppend);
344 }
345 outputFilename.append(".png");
346 // TODO(epoger): what about including the config type within outputFilename? That way,
347 // we could combine results of different config types without conflicting fi lenames.
348
316 if (NULL != jsonSummaryPtr) { 349 if (NULL != jsonSummaryPtr) {
317 // EPOGER: This is a hacky way of constructing the filename associated w ith the 350 if (!generatedHash) {
318 // image checksum; we assume that outputDir is not NULL, and we remove o utputDir 351 SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash));
319 // from fullPathname. 352 generatedHash = true;
320 // 353 }
321 // EPOGER: what about including the config type within hashFilename? Th at way, 354 jsonSummaryPtr->add(outputFilename.c_str(), hash);
322 // we could combine results of different config types without conflictin g filenames.
323 SkString hashFilename;
324 sk_tools::get_basename(&hashFilename, fullPathname);
325 jsonSummaryPtr->add(hashFilename.c_str(), bitmap);
326 } 355 }
327 356
357 // Update outputFilename AFTER adding to JSON summary, but BEFORE writing ou t the image file.
358 if (useChecksumBasedFilenames) {
359 if (!generatedHash) {
360 SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash));
361 generatedHash = true;
362 }
363 outputFilename.set(kJsonKey_Hashtype_Bitmap_64bitMD5);
364 outputFilename.append("_");
365 outputFilename.appendU64(hash);
366 outputFilename.append(".png");
367 }
368
369 SkASSERT(!outputDir.isEmpty()); // TODO(epoger): we want to remove this cons traint,
370 // as noted above
371 SkString fullPathname;
372 make_filepath(&fullPathname, outputDir, outputFilename);
328 return SkImageEncoder::EncodeFile(fullPathname.c_str(), bitmap, SkImageEncod er::kPNG_Type, 100); 373 return SkImageEncoder::EncodeFile(fullPathname.c_str(), bitmap, SkImageEncod er::kPNG_Type, 100);
329 } 374 }
330 375
331 /**
332 * If path is non NULL, append number to it, and call write() to write the
333 * provided canvas to a file. Returns true if path is NULL or if write() succeed s.
334 */
335 static bool writeAppendNumber(SkCanvas* canvas, const SkString* path, int number ,
336 ImageResultsSummary *jsonSummaryPtr) {
337 if (NULL == path) {
338 return true;
339 }
340 SkString pathWithNumber(*path);
341 pathWithNumber.appendf("%i", number);
342 return write(canvas, &pathWithNumber, jsonSummaryPtr);
343 }
344
345 //////////////////////////////////////////////////////////////////////////////// /////////////// 376 //////////////////////////////////////////////////////////////////////////////// ///////////////
346 377
347 SkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) { 378 SkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) {
348 // defer the canvas setup until the render step 379 // defer the canvas setup until the render step
349 return NULL; 380 return NULL;
350 } 381 }
351 382
352 // the size_t* parameter is deprecated, so we ignore it 383 // the size_t* parameter is deprecated, so we ignore it
353 static SkData* encode_bitmap_to_data(size_t*, const SkBitmap& bm) { 384 static SkData* encode_bitmap_to_data(size_t*, const SkBitmap& bm) {
354 return SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, 100); 385 return SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, 100);
355 } 386 }
356 387
357 bool RecordPictureRenderer::render(const SkString* path, SkBitmap** out) { 388 bool RecordPictureRenderer::render(SkBitmap** out) {
358 SkAutoTUnref<SkPicture> replayer(this->createPicture()); 389 SkAutoTUnref<SkPicture> replayer(this->createPicture());
359 SkCanvas* recorder = replayer->beginRecording(this->getViewWidth(), this->ge tViewHeight(), 390 SkCanvas* recorder = replayer->beginRecording(this->getViewWidth(), this->ge tViewHeight(),
360 this->recordFlags()); 391 this->recordFlags());
361 this->scaleToScaleFactor(recorder); 392 this->scaleToScaleFactor(recorder);
362 fPicture->draw(recorder); 393 fPicture->draw(recorder);
363 replayer->endRecording(); 394 replayer->endRecording();
364 if (path != NULL) { 395 if (!fOutputDir.isEmpty()) {
365 // Record the new picture as a new SKP with PNG encoded bitmaps. 396 // Record the new picture as a new SKP with PNG encoded bitmaps.
366 SkString skpPath(*path); 397 SkString skpPath;
367 // ".skp" was removed from 'path' before being passed in here. 398 make_filepath(&skpPath, fOutputDir, fInputFilename);
368 skpPath.append(".skp");
369 SkFILEWStream stream(skpPath.c_str()); 399 SkFILEWStream stream(skpPath.c_str());
370 replayer->serialize(&stream, &encode_bitmap_to_data); 400 replayer->serialize(&stream, &encode_bitmap_to_data);
371 return true; 401 return true;
372 } 402 }
373 return false; 403 return false;
374 } 404 }
375 405
376 SkString RecordPictureRenderer::getConfigNameInternal() { 406 SkString RecordPictureRenderer::getConfigNameInternal() {
377 return SkString("record"); 407 return SkString("record");
378 } 408 }
379 409
380 //////////////////////////////////////////////////////////////////////////////// /////////////// 410 //////////////////////////////////////////////////////////////////////////////// ///////////////
381 411
382 bool PipePictureRenderer::render(const SkString* path, SkBitmap** out) { 412 bool PipePictureRenderer::render(SkBitmap** out) {
383 SkASSERT(fCanvas.get() != NULL); 413 SkASSERT(fCanvas.get() != NULL);
384 SkASSERT(fPicture != NULL); 414 SkASSERT(fPicture != NULL);
385 if (NULL == fCanvas.get() || NULL == fPicture) { 415 if (NULL == fCanvas.get() || NULL == fPicture) {
386 return false; 416 return false;
387 } 417 }
388 418
389 PipeController pipeController(fCanvas.get()); 419 PipeController pipeController(fCanvas.get());
390 SkGPipeWriter writer; 420 SkGPipeWriter writer;
391 SkCanvas* pipeCanvas = writer.startRecording(&pipeController); 421 SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
392 pipeCanvas->drawPicture(*fPicture); 422 pipeCanvas->drawPicture(*fPicture);
393 writer.endRecording(); 423 writer.endRecording();
394 fCanvas->flush(); 424 fCanvas->flush();
395 if (NULL != path) { 425 if (!fOutputDir.isEmpty()) {
396 return write(fCanvas, path, fJsonSummaryPtr); 426 return write(fCanvas, fOutputDir, fInputFilename, fJsonSummaryPtr,
427 fUseChecksumBasedFilenames);
397 } 428 }
398 if (NULL != out) { 429 if (NULL != out) {
399 *out = SkNEW(SkBitmap); 430 *out = SkNEW(SkBitmap);
400 setup_bitmap(*out, fPicture->width(), fPicture->height()); 431 setup_bitmap(*out, fPicture->width(), fPicture->height());
401 fCanvas->readPixels(*out, 0, 0); 432 fCanvas->readPixels(*out, 0, 0);
402 } 433 }
403 return true; 434 return true;
404 } 435 }
405 436
406 SkString PipePictureRenderer::getConfigNameInternal() { 437 SkString PipePictureRenderer::getConfigNameInternal() {
407 return SkString("pipe"); 438 return SkString("pipe");
408 } 439 }
409 440
410 //////////////////////////////////////////////////////////////////////////////// /////////////// 441 //////////////////////////////////////////////////////////////////////////////// ///////////////
411 442
412 void SimplePictureRenderer::init(SkPicture* picture) { 443 void SimplePictureRenderer::init(SkPicture* picture, const SkString* outputDir,
413 INHERITED::init(picture); 444 const SkString* inputFilename, bool useChecksum BasedFilenames) {
445 INHERITED::init(picture, outputDir, inputFilename, useChecksumBasedFilenames );
414 this->buildBBoxHierarchy(); 446 this->buildBBoxHierarchy();
415 } 447 }
416 448
417 bool SimplePictureRenderer::render(const SkString* path, SkBitmap** out) { 449 bool SimplePictureRenderer::render(SkBitmap** out) {
418 SkASSERT(fCanvas.get() != NULL); 450 SkASSERT(fCanvas.get() != NULL);
419 SkASSERT(fPicture != NULL); 451 SkASSERT(fPicture != NULL);
420 if (NULL == fCanvas.get() || NULL == fPicture) { 452 if (NULL == fCanvas.get() || NULL == fPicture) {
421 return false; 453 return false;
422 } 454 }
423 455
424 fCanvas->drawPicture(*fPicture); 456 fCanvas->drawPicture(*fPicture);
425 fCanvas->flush(); 457 fCanvas->flush();
426 if (NULL != path) { 458 if (!fOutputDir.isEmpty()) {
427 return write(fCanvas, path, fJsonSummaryPtr); 459 return write(fCanvas, fOutputDir, fInputFilename, fJsonSummaryPtr,
460 fUseChecksumBasedFilenames);
428 } 461 }
429 462
430 if (NULL != out) { 463 if (NULL != out) {
431 *out = SkNEW(SkBitmap); 464 *out = SkNEW(SkBitmap);
432 setup_bitmap(*out, fPicture->width(), fPicture->height()); 465 setup_bitmap(*out, fPicture->width(), fPicture->height());
433 fCanvas->readPixels(*out, 0, 0); 466 fCanvas->readPixels(*out, 0, 0);
434 } 467 }
435 468
436 return true; 469 return true;
437 } 470 }
438 471
439 SkString SimplePictureRenderer::getConfigNameInternal() { 472 SkString SimplePictureRenderer::getConfigNameInternal() {
440 return SkString("simple"); 473 return SkString("simple");
441 } 474 }
442 475
443 //////////////////////////////////////////////////////////////////////////////// /////////////// 476 //////////////////////////////////////////////////////////////////////////////// ///////////////
444 477
445 TiledPictureRenderer::TiledPictureRenderer() 478 TiledPictureRenderer::TiledPictureRenderer()
446 : fTileWidth(kDefaultTileWidth) 479 : fTileWidth(kDefaultTileWidth)
447 , fTileHeight(kDefaultTileHeight) 480 , fTileHeight(kDefaultTileHeight)
448 , fTileWidthPercentage(0.0) 481 , fTileWidthPercentage(0.0)
449 , fTileHeightPercentage(0.0) 482 , fTileHeightPercentage(0.0)
450 , fTileMinPowerOf2Width(0) 483 , fTileMinPowerOf2Width(0)
451 , fCurrentTileOffset(-1) 484 , fCurrentTileOffset(-1)
452 , fTilesX(0) 485 , fTilesX(0)
453 , fTilesY(0) { } 486 , fTilesY(0) { }
454 487
455 void TiledPictureRenderer::init(SkPicture* pict) { 488 void TiledPictureRenderer::init(SkPicture* pict, const SkString* outputDir,
489 const SkString* inputFilename, bool useChecksumB asedFilenames) {
456 SkASSERT(pict != NULL); 490 SkASSERT(pict != NULL);
457 SkASSERT(0 == fTileRects.count()); 491 SkASSERT(0 == fTileRects.count());
458 if (NULL == pict || fTileRects.count() != 0) { 492 if (NULL == pict || fTileRects.count() != 0) {
459 return; 493 return;
460 } 494 }
461 495
462 // Do not call INHERITED::init(), which would create a (potentially large) c anvas which is not 496 // Do not call INHERITED::init(), which would create a (potentially large) c anvas which is not
463 // used by bench_pictures. 497 // used by bench_pictures.
464 fPicture = pict; 498 fPicture = pict;
499 this->CopyString(&fOutputDir, outputDir);
500 this->CopyString(&fInputFilename, inputFilename);
501 fUseChecksumBasedFilenames = useChecksumBasedFilenames;
465 fPicture->ref(); 502 fPicture->ref();
466 this->buildBBoxHierarchy(); 503 this->buildBBoxHierarchy();
467 504
468 if (fTileWidthPercentage > 0) { 505 if (fTileWidthPercentage > 0) {
469 fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->wi dth() / 100)); 506 fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->wi dth() / 100));
470 } 507 }
471 if (fTileHeightPercentage > 0) { 508 if (fTileHeightPercentage > 0) {
472 fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture-> height() / 100)); 509 fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture-> height() / 100));
473 } 510 }
474 511
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 return true; 653 return true;
617 } 654 }
618 return false; 655 return false;
619 } 656 }
620 657
621 void TiledPictureRenderer::drawCurrentTile() { 658 void TiledPictureRenderer::drawCurrentTile() {
622 SkASSERT(fCurrentTileOffset >= 0 && fCurrentTileOffset < fTileRects.count()) ; 659 SkASSERT(fCurrentTileOffset >= 0 && fCurrentTileOffset < fTileRects.count()) ;
623 draw_tile_to_canvas(fCanvas, fTileRects[fCurrentTileOffset], fPicture); 660 draw_tile_to_canvas(fCanvas, fTileRects[fCurrentTileOffset], fPicture);
624 } 661 }
625 662
626 bool TiledPictureRenderer::render(const SkString* path, SkBitmap** out) { 663 bool TiledPictureRenderer::render(SkBitmap** out) {
627 SkASSERT(fPicture != NULL); 664 SkASSERT(fPicture != NULL);
628 if (NULL == fPicture) { 665 if (NULL == fPicture) {
629 return false; 666 return false;
630 } 667 }
631 668
632 SkBitmap bitmap; 669 SkBitmap bitmap;
633 if (out){ 670 if (out){
634 *out = SkNEW(SkBitmap); 671 *out = SkNEW(SkBitmap);
635 setup_bitmap(*out, fPicture->width(), fPicture->height()); 672 setup_bitmap(*out, fPicture->width(), fPicture->height());
636 setup_bitmap(&bitmap, fTileWidth, fTileHeight); 673 setup_bitmap(&bitmap, fTileWidth, fTileHeight);
637 } 674 }
638 bool success = true; 675 bool success = true;
639 for (int i = 0; i < fTileRects.count(); ++i) { 676 for (int i = 0; i < fTileRects.count(); ++i) {
640 draw_tile_to_canvas(fCanvas, fTileRects[i], fPicture); 677 draw_tile_to_canvas(fCanvas, fTileRects[i], fPicture);
641 if (NULL != path) { 678 if (!fOutputDir.isEmpty()) {
642 success &= writeAppendNumber(fCanvas, path, i, fJsonSummaryPtr); 679 success &= write(fCanvas, fOutputDir, fInputFilename, fJsonSummaryPt r,
680 fUseChecksumBasedFilenames, &i);
643 } 681 }
644 if (NULL != out) { 682 if (NULL != out) {
645 if (fCanvas->readPixels(&bitmap, 0, 0)) { 683 if (fCanvas->readPixels(&bitmap, 0, 0)) {
646 // Add this tile to the entire bitmap. 684 // Add this tile to the entire bitmap.
647 bitmapCopyAtOffset(bitmap, *out, SkScalarFloorToInt(fTileRects[i ].left()), 685 bitmapCopyAtOffset(bitmap, *out, SkScalarFloorToInt(fTileRects[i ].left()),
648 SkScalarFloorToInt(fTileRects[i].top())); 686 SkScalarFloorToInt(fTileRects[i].top()));
649 } else { 687 } else {
650 success = false; 688 success = false;
651 } 689 }
652 } 690 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 return name; 729 return name;
692 } 730 }
693 731
694 //////////////////////////////////////////////////////////////////////////////// /////////////// 732 //////////////////////////////////////////////////////////////////////////////// ///////////////
695 733
696 // Holds all of the information needed to draw a set of tiles. 734 // Holds all of the information needed to draw a set of tiles.
697 class CloneData : public SkRunnable { 735 class CloneData : public SkRunnable {
698 736
699 public: 737 public:
700 CloneData(SkPicture* clone, SkCanvas* canvas, SkTDArray<SkRect>& rects, int start, int end, 738 CloneData(SkPicture* clone, SkCanvas* canvas, SkTDArray<SkRect>& rects, int start, int end,
701 SkRunnable* done, ImageResultsSummary* jsonSummaryPtr) 739 SkRunnable* done, ImageResultsSummary* jsonSummaryPtr, bool useChe cksumBasedFilenames)
702 : fClone(clone) 740 : fClone(clone)
703 , fCanvas(canvas) 741 , fCanvas(canvas)
704 , fPath(NULL)
705 , fRects(rects) 742 , fRects(rects)
706 , fStart(start) 743 , fStart(start)
707 , fEnd(end) 744 , fEnd(end)
708 , fSuccess(NULL) 745 , fSuccess(NULL)
709 , fDone(done) 746 , fDone(done)
710 , fJsonSummaryPtr(jsonSummaryPtr) { 747 , fJsonSummaryPtr(jsonSummaryPtr)
748 , fUseChecksumBasedFilenames(useChecksumBasedFilenames) {
711 SkASSERT(fDone != NULL); 749 SkASSERT(fDone != NULL);
712 } 750 }
713 751
714 virtual void run() SK_OVERRIDE { 752 virtual void run() SK_OVERRIDE {
715 SkGraphics::SetTLSFontCacheLimit(1024 * 1024); 753 SkGraphics::SetTLSFontCacheLimit(1024 * 1024);
716 754
717 SkBitmap bitmap; 755 SkBitmap bitmap;
718 if (fBitmap != NULL) { 756 if (fBitmap != NULL) {
719 // All tiles are the same size. 757 // All tiles are the same size.
720 setup_bitmap(&bitmap, SkScalarFloorToInt(fRects[0].width()), SkScala rFloorToInt(fRects[0].height())); 758 setup_bitmap(&bitmap, SkScalarFloorToInt(fRects[0].width()), SkScala rFloorToInt(fRects[0].height()));
721 } 759 }
722 760
723 for (int i = fStart; i < fEnd; i++) { 761 for (int i = fStart; i < fEnd; i++) {
724 draw_tile_to_canvas(fCanvas, fRects[i], fClone); 762 draw_tile_to_canvas(fCanvas, fRects[i], fClone);
725 if ((fPath != NULL) && !writeAppendNumber(fCanvas, fPath, i, fJsonSu mmaryPtr) 763 if ((!fOutputDir.isEmpty())
764 && !write(fCanvas, fOutputDir, fInputFilename, fJsonSummaryPtr,
765 fUseChecksumBasedFilenames, &i)
726 && fSuccess != NULL) { 766 && fSuccess != NULL) {
727 *fSuccess = false; 767 *fSuccess = false;
728 // If one tile fails to write to a file, do not continue drawing the rest. 768 // If one tile fails to write to a file, do not continue drawing the rest.
729 break; 769 break;
730 } 770 }
731 if (fBitmap != NULL) { 771 if (fBitmap != NULL) {
732 if (fCanvas->readPixels(&bitmap, 0, 0)) { 772 if (fCanvas->readPixels(&bitmap, 0, 0)) {
733 SkAutoLockPixels alp(*fBitmap); 773 SkAutoLockPixels alp(*fBitmap);
734 bitmapCopyAtOffset(bitmap, fBitmap, SkScalarFloorToInt(fRect s[i].left()), 774 bitmapCopyAtOffset(bitmap, fBitmap, SkScalarFloorToInt(fRect s[i].left()),
735 SkScalarFloorToInt(fRects[i].top())); 775 SkScalarFloorToInt(fRects[i].top()));
736 } else { 776 } else {
737 *fSuccess = false; 777 *fSuccess = false;
738 // If one tile fails to read pixels, do not continue drawing the rest. 778 // If one tile fails to read pixels, do not continue drawing the rest.
739 break; 779 break;
740 } 780 }
741 } 781 }
742 } 782 }
743 fDone->run(); 783 fDone->run();
744 } 784 }
745 785
746 void setPathAndSuccess(const SkString* path, bool* success) { 786 void setPathsAndSuccess(const SkString& outputDir, const SkString& inputFile name,
747 fPath = path; 787 bool* success) {
788 fOutputDir.set(outputDir);
789 fInputFilename.set(inputFilename);
748 fSuccess = success; 790 fSuccess = success;
749 } 791 }
750 792
751 void setBitmap(SkBitmap* bitmap) { 793 void setBitmap(SkBitmap* bitmap) {
752 fBitmap = bitmap; 794 fBitmap = bitmap;
753 } 795 }
754 796
755 private: 797 private:
756 // All pointers unowned. 798 // All pointers unowned.
757 SkPicture* fClone; // Picture to draw from. Each CloneData has a unique one which 799 SkPicture* fClone; // Picture to draw from. Each CloneData has a unique one which
758 // is threadsafe. 800 // is threadsafe.
759 SkCanvas* fCanvas; // Canvas to draw to. Reused for each tile. 801 SkCanvas* fCanvas; // Canvas to draw to. Reused for each tile.
760 const SkString* fPath; // If non-null, path to write the result to as a PNG. 802 SkString fOutputDir; // If not empty, write results into this dir ectory.
803 SkString fInputFilename; // Filename of input SkPicture file.
761 SkTDArray<SkRect>& fRects; // All tiles of the picture. 804 SkTDArray<SkRect>& fRects; // All tiles of the picture.
762 const int fStart; // Range of tiles drawn by this thread. 805 const int fStart; // Range of tiles drawn by this thread.
763 const int fEnd; 806 const int fEnd;
764 bool* fSuccess; // Only meaningful if path is non-null. Shar ed by all threads, 807 bool* fSuccess; // Only meaningful if path is non-null. Shar ed by all threads,
765 // and only set to false upon failure to wri te to a PNG. 808 // and only set to false upon failure to wri te to a PNG.
766 SkRunnable* fDone; 809 SkRunnable* fDone;
767 SkBitmap* fBitmap; 810 SkBitmap* fBitmap;
768 ImageResultsSummary* fJsonSummaryPtr; 811 ImageResultsSummary* fJsonSummaryPtr;
812 bool fUseChecksumBasedFilenames;
769 }; 813 };
770 814
771 MultiCorePictureRenderer::MultiCorePictureRenderer(int threadCount) 815 MultiCorePictureRenderer::MultiCorePictureRenderer(int threadCount)
772 : fNumThreads(threadCount) 816 : fNumThreads(threadCount)
773 , fThreadPool(threadCount) 817 , fThreadPool(threadCount)
774 , fCountdown(threadCount) { 818 , fCountdown(threadCount) {
775 // Only need to create fNumThreads - 1 clones, since one thread will use the base 819 // Only need to create fNumThreads - 1 clones, since one thread will use the base
776 // picture. 820 // picture.
777 fPictureClones = SkNEW_ARRAY(SkPicture, fNumThreads - 1); 821 fPictureClones = SkNEW_ARRAY(SkPicture, fNumThreads - 1);
778 fCloneData = SkNEW_ARRAY(CloneData*, fNumThreads); 822 fCloneData = SkNEW_ARRAY(CloneData*, fNumThreads);
779 } 823 }
780 824
781 void MultiCorePictureRenderer::init(SkPicture *pict) { 825 void MultiCorePictureRenderer::init(SkPicture *pict, const SkString* outputDir,
826 const SkString* inputFilename, bool useCheck sumBasedFilenames) {
782 // Set fPicture and the tiles. 827 // Set fPicture and the tiles.
783 this->INHERITED::init(pict); 828 this->INHERITED::init(pict, outputDir, inputFilename, useChecksumBasedFilena mes);
784 for (int i = 0; i < fNumThreads; ++i) { 829 for (int i = 0; i < fNumThreads; ++i) {
785 *fCanvasPool.append() = this->setupCanvas(this->getTileWidth(), this->ge tTileHeight()); 830 *fCanvasPool.append() = this->setupCanvas(this->getTileWidth(), this->ge tTileHeight());
786 } 831 }
787 // Only need to create fNumThreads - 1 clones, since one thread will use the base picture. 832 // Only need to create fNumThreads - 1 clones, since one thread will use the base picture.
788 fPicture->clone(fPictureClones, fNumThreads - 1); 833 fPicture->clone(fPictureClones, fNumThreads - 1);
789 // Populate each thread with the appropriate data. 834 // Populate each thread with the appropriate data.
790 // Group the tiles into nearly equal size chunks, rounding up so we're sure to cover them all. 835 // Group the tiles into nearly equal size chunks, rounding up so we're sure to cover them all.
791 const int chunkSize = (fTileRects.count() + fNumThreads - 1) / fNumThreads; 836 const int chunkSize = (fTileRects.count() + fNumThreads - 1) / fNumThreads;
792 837
793 for (int i = 0; i < fNumThreads; i++) { 838 for (int i = 0; i < fNumThreads; i++) {
794 SkPicture* pic; 839 SkPicture* pic;
795 if (i == fNumThreads-1) { 840 if (i == fNumThreads-1) {
796 // The last set will use the original SkPicture. 841 // The last set will use the original SkPicture.
797 pic = fPicture; 842 pic = fPicture;
798 } else { 843 } else {
799 pic = &fPictureClones[i]; 844 pic = &fPictureClones[i];
800 } 845 }
801 const int start = i * chunkSize; 846 const int start = i * chunkSize;
802 const int end = SkMin32(start + chunkSize, fTileRects.count()); 847 const int end = SkMin32(start + chunkSize, fTileRects.count());
803 fCloneData[i] = SkNEW_ARGS(CloneData, 848 fCloneData[i] = SkNEW_ARGS(CloneData,
804 (pic, fCanvasPool[i], fTileRects, start, end, &fCountdown, 849 (pic, fCanvasPool[i], fTileRects, start, end, &fCountdown,
805 fJsonSummaryPtr)); 850 fJsonSummaryPtr, useChecksumBasedFilenames)) ;
806 } 851 }
807 } 852 }
808 853
809 bool MultiCorePictureRenderer::render(const SkString *path, SkBitmap** out) { 854 bool MultiCorePictureRenderer::render(SkBitmap** out) {
810 bool success = true; 855 bool success = true;
811 if (path != NULL) { 856 if (!fOutputDir.isEmpty()) {
812 for (int i = 0; i < fNumThreads-1; i++) { 857 for (int i = 0; i < fNumThreads-1; i++) {
813 fCloneData[i]->setPathAndSuccess(path, &success); 858 fCloneData[i]->setPathsAndSuccess(fOutputDir, fInputFilename, &succe ss);
814 } 859 }
815 } 860 }
816 861
817 if (NULL != out) { 862 if (NULL != out) {
818 *out = SkNEW(SkBitmap); 863 *out = SkNEW(SkBitmap);
819 setup_bitmap(*out, fPicture->width(), fPicture->height()); 864 setup_bitmap(*out, fPicture->width(), fPicture->height());
820 for (int i = 0; i < fNumThreads; i++) { 865 for (int i = 0; i < fNumThreads; i++) {
821 fCloneData[i]->setBitmap(*out); 866 fCloneData[i]->setBitmap(*out);
822 } 867 }
823 } else { 868 } else {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 //////////////////////////////////////////////////////////////////////////////// /////////////// 906 //////////////////////////////////////////////////////////////////////////////// ///////////////
862 907
863 void PlaybackCreationRenderer::setup() { 908 void PlaybackCreationRenderer::setup() {
864 fReplayer.reset(this->createPicture()); 909 fReplayer.reset(this->createPicture());
865 SkCanvas* recorder = fReplayer->beginRecording(this->getViewWidth(), this->g etViewHeight(), 910 SkCanvas* recorder = fReplayer->beginRecording(this->getViewWidth(), this->g etViewHeight(),
866 this->recordFlags()); 911 this->recordFlags());
867 this->scaleToScaleFactor(recorder); 912 this->scaleToScaleFactor(recorder);
868 fPicture->draw(recorder); 913 fPicture->draw(recorder);
869 } 914 }
870 915
871 bool PlaybackCreationRenderer::render(const SkString*, SkBitmap** out) { 916 bool PlaybackCreationRenderer::render(SkBitmap** out) {
872 fReplayer->endRecording(); 917 fReplayer->endRecording();
873 // Since this class does not actually render, return false. 918 // Since this class does not actually render, return false.
874 return false; 919 return false;
875 } 920 }
876 921
877 SkString PlaybackCreationRenderer::getConfigNameInternal() { 922 SkString PlaybackCreationRenderer::getConfigNameInternal() {
878 return SkString("playback_creation"); 923 return SkString("playback_creation");
879 } 924 }
880 925
881 //////////////////////////////////////////////////////////////////////////////// /////////////// 926 //////////////////////////////////////////////////////////////////////////////// ///////////////
(...skipping 26 matching lines...) Expand all
908 fPicture->height(), fGridInfo)); 953 fPicture->height(), fGridInfo));
909 } 954 }
910 SkASSERT(0); // invalid bbhType 955 SkASSERT(0); // invalid bbhType
911 return NULL; 956 return NULL;
912 } 957 }
913 958
914 /////////////////////////////////////////////////////////////////////////////// 959 ///////////////////////////////////////////////////////////////////////////////
915 960
916 class GatherRenderer : public PictureRenderer { 961 class GatherRenderer : public PictureRenderer {
917 public: 962 public:
918 virtual bool render(const SkString* path, SkBitmap** out = NULL) 963 virtual bool render(SkBitmap** out = NULL)
919 SK_OVERRIDE { 964 SK_OVERRIDE {
920 SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->width()), 965 SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
921 SkIntToScalar(fPicture->height())); 966 SkIntToScalar(fPicture->height()));
922 SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds); 967 SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds);
923 SkSafeUnref(data); 968 SkSafeUnref(data);
924 969
925 return NULL == path; // we don't have anything to write 970 return (fOutputDir.isEmpty()); // we don't have anything to write
926 } 971 }
927 972
928 private: 973 private:
929 virtual SkString getConfigNameInternal() SK_OVERRIDE { 974 virtual SkString getConfigNameInternal() SK_OVERRIDE {
930 return SkString("gather_pixelrefs"); 975 return SkString("gather_pixelrefs");
931 } 976 }
932 }; 977 };
933 978
934 PictureRenderer* CreateGatherPixelRefsRenderer() { 979 PictureRenderer* CreateGatherPixelRefsRenderer() {
935 return SkNEW(GatherRenderer); 980 return SkNEW(GatherRenderer);
936 } 981 }
937 982
938 /////////////////////////////////////////////////////////////////////////////// 983 ///////////////////////////////////////////////////////////////////////////////
939 984
940 class PictureCloneRenderer : public PictureRenderer { 985 class PictureCloneRenderer : public PictureRenderer {
941 public: 986 public:
942 virtual bool render(const SkString* path, SkBitmap** out = NULL) 987 virtual bool render(SkBitmap** out = NULL)
943 SK_OVERRIDE { 988 SK_OVERRIDE {
944 for (int i = 0; i < 100; ++i) { 989 for (int i = 0; i < 100; ++i) {
945 SkPicture* clone = fPicture->clone(); 990 SkPicture* clone = fPicture->clone();
946 SkSafeUnref(clone); 991 SkSafeUnref(clone);
947 } 992 }
948 993
949 return NULL == path; // we don't have anything to write 994 return (fOutputDir.isEmpty()); // we don't have anything to write
950 } 995 }
951 996
952 private: 997 private:
953 virtual SkString getConfigNameInternal() SK_OVERRIDE { 998 virtual SkString getConfigNameInternal() SK_OVERRIDE {
954 return SkString("picture_clone"); 999 return SkString("picture_clone");
955 } 1000 }
956 }; 1001 };
957 1002
958 PictureRenderer* CreatePictureCloneRenderer() { 1003 PictureRenderer* CreatePictureCloneRenderer() {
959 return SkNEW(PictureCloneRenderer); 1004 return SkNEW(PictureCloneRenderer);
960 } 1005 }
961 1006
962 } // namespace sk_tools 1007 } // namespace sk_tools
OLDNEW
« no previous file with comments | « tools/PictureRenderer.h ('k') | tools/bbh_shootout.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698