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

Side by Side Diff: tools/PictureRenderer.cpp

Issue 226293002: add explicit filepaths to render_pictures JSON summary (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebase Created 6 years, 8 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/picture_utils.h » ('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"
11 #include "SkBitmapHasher.h" 11 #include "SkBitmapHasher.h"
12 #include "SkCanvas.h" 12 #include "SkCanvas.h"
13 #include "SkData.h" 13 #include "SkData.h"
14 #include "SkDevice.h" 14 #include "SkDevice.h"
15 #include "SkDiscardableMemoryPool.h" 15 #include "SkDiscardableMemoryPool.h"
16 #include "SkGPipe.h" 16 #include "SkGPipe.h"
17 #if SK_SUPPORT_GPU 17 #if SK_SUPPORT_GPU
18 #include "gl/GrGLDefines.h" 18 #include "gl/GrGLDefines.h"
19 #include "SkGpuDevice.h" 19 #include "SkGpuDevice.h"
20 #endif 20 #endif
21 #include "SkGraphics.h" 21 #include "SkGraphics.h"
22 #include "SkImageEncoder.h" 22 #include "SkImageEncoder.h"
23 #include "SkMaskFilter.h" 23 #include "SkMaskFilter.h"
24 #include "SkMatrix.h" 24 #include "SkMatrix.h"
25 #include "SkOSFile.h"
25 #include "SkPicture.h" 26 #include "SkPicture.h"
26 #include "SkPictureUtils.h" 27 #include "SkPictureUtils.h"
27 #include "SkPixelRef.h" 28 #include "SkPixelRef.h"
28 #include "SkQuadTree.h" 29 #include "SkQuadTree.h"
29 #include "SkQuadTreePicture.h" 30 #include "SkQuadTreePicture.h"
30 #include "SkRTree.h" 31 #include "SkRTree.h"
31 #include "SkScalar.h" 32 #include "SkScalar.h"
32 #include "SkStream.h" 33 #include "SkStream.h"
33 #include "SkString.h" 34 #include "SkString.h"
34 #include "SkTemplates.h" 35 #include "SkTemplates.h"
35 #include "SkTileGridPicture.h" 36 #include "SkTileGridPicture.h"
36 #include "SkTDArray.h" 37 #include "SkTDArray.h"
37 #include "SkThreadUtils.h" 38 #include "SkThreadUtils.h"
38 #include "SkTypes.h" 39 #include "SkTypes.h"
39 40
40 static inline SkScalar scalar_log2(SkScalar x) { 41 static inline SkScalar scalar_log2(SkScalar x) {
41 static const SkScalar log2_conversion_factor = SkScalarDiv(1, SkScalarLog(2) ); 42 static const SkScalar log2_conversion_factor = SkScalarDiv(1, SkScalarLog(2) );
42 43
43 return SkScalarLog(x) * log2_conversion_factor; 44 return SkScalarLog(x) * log2_conversion_factor;
44 } 45 }
45 46
46 namespace sk_tools { 47 namespace sk_tools {
47 48
48 enum { 49 enum {
49 kDefaultTileWidth = 256, 50 kDefaultTileWidth = 256,
50 kDefaultTileHeight = 256 51 kDefaultTileHeight = 256
51 }; 52 };
52 53
53 /* TODO(epoger): These constants are already maintained in 2 other places: 54 /*
54 * gm/gm_json.py and gm/gm_expectations.cpp. We shouldn't add yet a third place . 55 * TODO(epoger): Make constant strings consistent instead of mixing hypenated an d camel-caps.
56 *
57 * TODO(epoger): Similar constants are already maintained in 2 other places:
58 * 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. 59 * Figure out a way to share the definitions instead.
60 *
61 * Note that, as of https://codereview.chromium.org/226293002 , the JSON
62 * schema used here has started to differ from the one in gm_expectations.cpp .
63 * TODO(epoger): Consider getting GM and render_pictures to use the same JSON
64 * output module.
56 */ 65 */
57 const static char kJsonKey_ActualResults[] = "actual-results"; 66 const static char kJsonKey_ActualResults[] = "actual-results";
58 const static char kJsonKey_ActualResults_NoComparison[] = "no-comparison"; 67 const static char kJsonKey_Header[] = "header";
59 const static char kJsonKey_Hashtype_Bitmap_64bitMD5[] = "bitmap-64bitMD5"; 68 const static char kJsonKey_Header_Type[] = "type";
69 const static char kJsonKey_Header_Revision[] = "revision"; // unique within Typ e
70 const static char kJsonKey_Image_ChecksumAlgorithm[] = "checksumAlgorithm";
71 const static char kJsonKey_Image_ChecksumValue[] = "checksumValue";
72 const static char kJsonKey_Image_ComparisonResult[] = "comparisonResult";
73 const static char kJsonKey_Image_Filepath[] = "filepath";
74 const static char kJsonKey_Source_TiledImages[] = "tiled-images";
75 const static char kJsonKey_Source_WholeImage[] = "whole-image";
76 // Values (not keys) that are written out by this JSON generator
77 const static char kJsonValue_Header_Type[] = "ChecksummedImages";
78 const static int kJsonValue_Header_Revision = 1;
79 const static char kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5[] = "bitmap- 64bitMD5";
80 const static char kJsonValue_Image_ComparisonResult_NoComparison[] = "no-compari son";
60 81
61 void ImageResultsSummary::add(const char *testName, uint64_t hash) { 82 void ImageResultsSummary::add(const char *sourceName, const char *fileName, uint 64_t hash,
62 Json::Value jsonTypeValuePair; 83 const int *tileNumber) {
63 jsonTypeValuePair.append(Json::Value(kJsonKey_Hashtype_Bitmap_64bitMD5)); 84 Json::Value image;
64 jsonTypeValuePair.append(Json::UInt64(hash)); 85 image[kJsonKey_Image_ChecksumAlgorithm] = kJsonValue_Image_ChecksumAlgorithm _Bitmap64bitMD5;
65 fActualResultsNoComparison[testName] = jsonTypeValuePair; 86 image[kJsonKey_Image_ChecksumValue] = Json::UInt64(hash);
87 image[kJsonKey_Image_ComparisonResult] = kJsonValue_Image_ComparisonResult_N oComparison;
88 image[kJsonKey_Image_Filepath] = fileName;
89 if (NULL == tileNumber) {
90 fActualResults[sourceName][kJsonKey_Source_WholeImage] = image;
91 } else {
92 fActualResults[sourceName][kJsonKey_Source_TiledImages][*tileNumber] = i mage;
93 }
66 } 94 }
67 95
68 void ImageResultsSummary::add(const char *testName, const SkBitmap& bitmap) { 96 void ImageResultsSummary::add(const char *sourceName, const char *fileName, cons t SkBitmap& bitmap,
97 const int *tileNumber) {
69 uint64_t hash; 98 uint64_t hash;
70 SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash)); 99 SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash));
71 this->add(testName, hash); 100 this->add(sourceName, fileName, hash, tileNumber);
72 } 101 }
73 102
74 void ImageResultsSummary::writeToFile(const char *filename) { 103 void ImageResultsSummary::writeToFile(const char *filename) {
75 Json::Value actualResults; 104 Json::Value header;
76 actualResults[kJsonKey_ActualResults_NoComparison] = fActualResultsNoCompari son; 105 header[kJsonKey_Header_Type] = kJsonValue_Header_Type;
106 header[kJsonKey_Header_Revision] = kJsonValue_Header_Revision;
77 Json::Value root; 107 Json::Value root;
78 root[kJsonKey_ActualResults] = actualResults; 108 root[kJsonKey_Header] = header;
109 root[kJsonKey_ActualResults] = fActualResults;
79 std::string jsonStdString = root.toStyledString(); 110 std::string jsonStdString = root.toStyledString();
80 SkFILEWStream stream(filename); 111 SkFILEWStream stream(filename);
81 stream.write(jsonStdString.c_str(), jsonStdString.length()); 112 stream.write(jsonStdString.c_str(), jsonStdString.length());
82 } 113 }
83 114
84 void PictureRenderer::init(SkPicture* pict, const SkString* outputDir, 115 void PictureRenderer::init(SkPicture* pict, const SkString* outputDir,
85 const SkString* inputFilename, bool useChecksumBasedF ilenames) { 116 const SkString* inputFilename, bool useChecksumBasedF ilenames) {
86 this->CopyString(&fOutputDir, outputDir); 117 this->CopyString(&fOutputDir, outputDir);
87 this->CopyString(&fInputFilename, inputFilename); 118 this->CopyString(&fInputFilename, inputFilename);
88 fUseChecksumBasedFilenames = useChecksumBasedFilenames; 119 fUseChecksumBasedFilenames = useChecksumBasedFilenames;
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 } 328 }
298 329
299 /** 330 /**
300 * Write the canvas to the specified path. 331 * Write the canvas to the specified path.
301 * 332 *
302 * @param canvas Must be non-null. Canvas to be written to a file. 333 * @param canvas Must be non-null. Canvas to be written to a file.
303 * @param outputDir If nonempty, write the binary image to a file within this di rectory. 334 * @param outputDir If nonempty, write the binary image to a file within this di rectory.
304 * @param inputFilename If we are writing out a binary image, use this to build its filename. 335 * @param inputFilename If we are writing out a binary image, use this to build its filename.
305 * @param jsonSummaryPtr If not null, add image results to this summary. 336 * @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. 337 * @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. 338 * @param tileNumberPtr If not null, which tile number this image contains.
308 * @return bool True if the Canvas is written to a file. 339 * @return bool True if the Canvas is written to a file.
309 * 340 *
310 * TODO(epoger): Right now, all canvases must pass through this function in orde r to be appended 341 * TODO(epoger): Right now, all canvases must pass through this function in orde r to be appended
311 * to the ImageResultsSummary. We need some way to add bitmaps to the ImageResu ltsSummary 342 * to the ImageResultsSummary. We need some way to add bitmaps to the ImageResu ltsSummary
312 * even if --writePath has not been specified (and thus this function is not cal led). 343 * even if --writePath has not been specified (and thus this function is not cal led).
313 * 344 *
314 * One fix would be to pass in these path elements separately, and allow this fu nction to be 345 * One fix would be to pass in these path elements separately, and allow this fu nction to be
315 * called even if --writePath was not specified... 346 * called even if --writePath was not specified...
316 * const char *outputDir // NULL if we don't want to write image files to dis k 347 * const char *outputDir // NULL if we don't want to write image files to dis k
317 * const char *filename // name we use within JSON summary, and as the filen ame within outputDir 348 * const char *filename // name we use within JSON summary, and as the filen ame within outputDir
318 * 349 *
319 * UPDATE: Now that outputDir and inputFilename are passed separately, we should be able to do that. 350 * UPDATE: Now that outputDir and inputFilename are passed separately, we should be able to do that.
320 */ 351 */
321 static bool write(SkCanvas* canvas, const SkString& outputDir, const SkString& i nputFilename, 352 static bool write(SkCanvas* canvas, const SkString& outputDir, const SkString& i nputFilename,
322 ImageResultsSummary *jsonSummaryPtr, bool useChecksumBasedFile names, 353 ImageResultsSummary *jsonSummaryPtr, bool useChecksumBasedFile names,
323 const int* numberToAppend=NULL) { 354 const int* tileNumberPtr=NULL) {
324 SkASSERT(canvas != NULL); 355 SkASSERT(canvas != NULL);
325 if (NULL == canvas) { 356 if (NULL == canvas) {
326 return false; 357 return false;
327 } 358 }
328 359
329 SkBitmap bitmap; 360 SkBitmap bitmap;
330 SkISize size = canvas->getDeviceSize(); 361 SkISize size = canvas->getDeviceSize();
331 sk_tools::setup_bitmap(&bitmap, size.width(), size.height()); 362 sk_tools::setup_bitmap(&bitmap, size.width(), size.height());
332 363
333 // Make sure we only compute the bitmap hash once (at most). 364 // Make sure we only compute the bitmap hash once (at most).
334 uint64_t hash; 365 uint64_t hash;
335 bool generatedHash = false; 366 bool generatedHash = false;
336 367
337 canvas->readPixels(&bitmap, 0, 0); 368 canvas->readPixels(&bitmap, 0, 0);
338 sk_tools::force_all_opaque(bitmap); 369 sk_tools::force_all_opaque(bitmap);
339 370
340 SkString outputFilename(inputFilename); 371 SkString escapedInputFilename(inputFilename);
341 outputFilename.remove(outputFilename.size() - 4, 4); 372 replace_char(&escapedInputFilename, '.', '_');
342 if (NULL != numberToAppend) { 373
343 outputFilename.appendf("%i", *numberToAppend);
344 }
345 outputFilename.append(".png");
346 // TODO(epoger): what about including the config type within outputFilename? That way, 374 // 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. 375 // we could combine results of different config types without conflicting fi lenames.
348 376 SkString outputFilename;
349 if (NULL != jsonSummaryPtr) { 377 const char *outputSubdirPtr = NULL;
378 if (useChecksumBasedFilenames) {
350 SkASSERT(!generatedHash); 379 SkASSERT(!generatedHash);
351 SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash)); 380 SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash));
352 generatedHash = true; 381 generatedHash = true;
353 382
354 jsonSummaryPtr->add(outputFilename.c_str(), hash); 383 outputSubdirPtr = escapedInputFilename.c_str();
384 outputFilename.set(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5);
385 outputFilename.append("_");
386 outputFilename.appendU64(hash);
387 } else {
388 outputFilename.set(escapedInputFilename);
389 if (NULL != tileNumberPtr) {
390 outputFilename.append("-tile");
391 outputFilename.appendS32(*tileNumberPtr);
392 }
355 } 393 }
394 outputFilename.append(".png");
356 395
357 // Update outputFilename AFTER adding to JSON summary, but BEFORE writing ou t the image file. 396 if (NULL != jsonSummaryPtr) {
358 if (useChecksumBasedFilenames) {
359 if (!generatedHash) { 397 if (!generatedHash) {
360 SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash)); 398 SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash));
361 generatedHash = true; 399 generatedHash = true;
362 } 400 }
363 outputFilename.set(kJsonKey_Hashtype_Bitmap_64bitMD5); 401
364 outputFilename.append("_"); 402 SkString outputRelativePath;
365 outputFilename.appendU64(hash); 403 if (outputSubdirPtr) {
366 outputFilename.append(".png"); 404 outputRelativePath.set(outputSubdirPtr);
405 outputRelativePath.append("/"); // always use "/", even on Windows
406 outputRelativePath.append(outputFilename);
407 } else {
408 outputRelativePath.set(outputFilename);
409 }
410
411 jsonSummaryPtr->add(inputFilename.c_str(), outputRelativePath.c_str(),
412 hash, tileNumberPtr);
367 } 413 }
368 414
369 SkASSERT(!outputDir.isEmpty()); // TODO(epoger): we want to remove this cons traint, 415 SkASSERT(!outputDir.isEmpty()); // TODO(epoger): we want to remove this cons traint,
370 // as noted above 416 // as noted above
371 SkString fullPathname; 417 SkString dirPath;
372 make_filepath(&fullPathname, outputDir, outputFilename); 418 if (outputSubdirPtr) {
373 return SkImageEncoder::EncodeFile(fullPathname.c_str(), bitmap, SkImageEncod er::kPNG_Type, 100); 419 dirPath = SkOSPath::SkPathJoin(outputDir.c_str(), outputSubdirPtr);
420 sk_mkdir(dirPath.c_str());
421 } else {
422 dirPath.set(outputDir);
423 }
424 SkString fullPath = SkOSPath::SkPathJoin(dirPath.c_str(), outputFilename.c_s tr());
425 return SkImageEncoder::EncodeFile(fullPath.c_str(), bitmap, SkImageEncoder:: kPNG_Type, 100);
374 } 426 }
375 427
376 //////////////////////////////////////////////////////////////////////////////// /////////////// 428 //////////////////////////////////////////////////////////////////////////////// ///////////////
377 429
378 SkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) { 430 SkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) {
379 // defer the canvas setup until the render step 431 // defer the canvas setup until the render step
380 return NULL; 432 return NULL;
381 } 433 }
382 434
383 // the size_t* parameter is deprecated, so we ignore it 435 // the size_t* parameter is deprecated, so we ignore it
384 static SkData* encode_bitmap_to_data(size_t*, const SkBitmap& bm) { 436 static SkData* encode_bitmap_to_data(size_t*, const SkBitmap& bm) {
385 return SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, 100); 437 return SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, 100);
386 } 438 }
387 439
388 bool RecordPictureRenderer::render(SkBitmap** out) { 440 bool RecordPictureRenderer::render(SkBitmap** out) {
389 SkAutoTUnref<SkPicture> replayer(this->createPicture()); 441 SkAutoTUnref<SkPicture> replayer(this->createPicture());
390 SkCanvas* recorder = replayer->beginRecording(this->getViewWidth(), this->ge tViewHeight(), 442 SkCanvas* recorder = replayer->beginRecording(this->getViewWidth(), this->ge tViewHeight(),
391 this->recordFlags()); 443 this->recordFlags());
392 this->scaleToScaleFactor(recorder); 444 this->scaleToScaleFactor(recorder);
393 fPicture->draw(recorder); 445 fPicture->draw(recorder);
394 replayer->endRecording(); 446 replayer->endRecording();
395 if (!fOutputDir.isEmpty()) { 447 if (!fOutputDir.isEmpty()) {
396 // Record the new picture as a new SKP with PNG encoded bitmaps. 448 // Record the new picture as a new SKP with PNG encoded bitmaps.
397 SkString skpPath; 449 SkString skpPath = SkOSPath::SkPathJoin(fOutputDir.c_str(), fInputFilena me.c_str());
398 make_filepath(&skpPath, fOutputDir, fInputFilename);
399 SkFILEWStream stream(skpPath.c_str()); 450 SkFILEWStream stream(skpPath.c_str());
400 replayer->serialize(&stream, &encode_bitmap_to_data); 451 replayer->serialize(&stream, &encode_bitmap_to_data);
401 return true; 452 return true;
402 } 453 }
403 return false; 454 return false;
404 } 455 }
405 456
406 SkString RecordPictureRenderer::getConfigNameInternal() { 457 SkString RecordPictureRenderer::getConfigNameInternal() {
407 return SkString("record"); 458 return SkString("record");
408 } 459 }
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after
995 virtual SkString getConfigNameInternal() SK_OVERRIDE { 1046 virtual SkString getConfigNameInternal() SK_OVERRIDE {
996 return SkString("picture_clone"); 1047 return SkString("picture_clone");
997 } 1048 }
998 }; 1049 };
999 1050
1000 PictureRenderer* CreatePictureCloneRenderer() { 1051 PictureRenderer* CreatePictureCloneRenderer() {
1001 return SkNEW(PictureCloneRenderer); 1052 return SkNEW(PictureCloneRenderer);
1002 } 1053 }
1003 1054
1004 } // namespace sk_tools 1055 } // namespace sk_tools
OLDNEW
« no previous file with comments | « tools/PictureRenderer.h ('k') | tools/picture_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698