diff options
author | mtklein <mtklein@chromium.org> | 2015-10-20 14:29:10 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-10-20 14:29:10 -0700 |
commit | 0c768a2f330e0e8f0883e174260928097d33e526 (patch) | |
tree | 7b4a19cdbd16d3d1bce3308d7366dc0f9b3cb47e /tools | |
parent | ef33b1e739b23a1201100ff17a572da85b03d9af (diff) |
Clean up some dead code.
This cleans up tools/ code, or code that should have been in tools/.
The only interesting code change trims features off of PictureRenderer.
It's still in use by a few useful-looking tools.
BUG=skia:
Review URL: https://codereview.chromium.org/1416913003
Diffstat (limited to 'tools')
-rw-r--r-- | tools/CopyTilesRenderer.cpp | 118 | ||||
-rw-r--r-- | tools/CopyTilesRenderer.h | 58 | ||||
-rw-r--r-- | tools/PictureBenchmark.cpp | 246 | ||||
-rw-r--r-- | tools/PictureBenchmark.h | 72 | ||||
-rw-r--r-- | tools/PictureRenderer.cpp | 99 | ||||
-rw-r--r-- | tools/PictureRenderer.h | 20 | ||||
-rw-r--r-- | tools/PictureRenderingFlags.cpp | 373 | ||||
-rw-r--r-- | tools/PictureRenderingFlags.h | 33 | ||||
-rw-r--r-- | tools/PictureResultsWriter.h | 312 | ||||
-rw-r--r-- | tools/bench_pictures.cfg | 83 | ||||
-rw-r--r-- | tools/bench_pictures_cfg_helper.py | 107 | ||||
-rw-r--r-- | tools/bench_pictures_main.cpp | 481 | ||||
-rw-r--r-- | tools/chromium/chrome_changes | 7 | ||||
-rw-r--r-- | tools/dump_record.cpp | 83 | ||||
-rw-r--r-- | tools/flatten.cpp | 51 | ||||
-rw-r--r-- | tools/image_expectations.cpp | 259 | ||||
-rw-r--r-- | tools/image_expectations.h | 232 | ||||
-rw-r--r-- | tools/render_pictures_main.cpp | 511 |
18 files changed, 3 insertions, 3142 deletions
diff --git a/tools/CopyTilesRenderer.cpp b/tools/CopyTilesRenderer.cpp deleted file mode 100644 index a78d772c68..0000000000 --- a/tools/CopyTilesRenderer.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "picture_utils.h" -#include "CopyTilesRenderer.h" -#include "SkCanvas.h" -#include "SkDevice.h" -#include "SkImageEncoder.h" -#include "SkMultiPictureDraw.h" -#include "SkPicture.h" -#include "SkPixelRef.h" -#include "SkRect.h" -#include "SkString.h" - -namespace sk_tools { -#if SK_SUPPORT_GPU - CopyTilesRenderer::CopyTilesRenderer(const GrContextOptions& opts, int x, int y) - : INHERITED(opts) - , fXTilesPerLargeTile(x) - , fYTilesPerLargeTile(y) { } -#else - CopyTilesRenderer::CopyTilesRenderer(int x, int y) - : fXTilesPerLargeTile(x) - , fYTilesPerLargeTile(y) { } -#endif - void CopyTilesRenderer::init(const SkPicture* pict, const SkString* writePath, - const SkString* mismatchPath, const SkString* inputFilename, - bool useChecksumBasedFilenames, bool useMultiPictureDraw) { - // Do not call INHERITED::init(), which would create a (potentially large) canvas which is - // not used by bench_pictures. - SkASSERT(pict != nullptr); - // Only work with absolute widths (as opposed to percentages). - SkASSERT(this->getTileWidth() != 0 && this->getTileHeight() != 0); - fPicture.reset(SkRef(pict)); - this->CopyString(&fWritePath, writePath); - this->CopyString(&fMismatchPath, mismatchPath); - this->CopyString(&fInputFilename, inputFilename); - fUseChecksumBasedFilenames = useChecksumBasedFilenames; - fUseMultiPictureDraw = useMultiPictureDraw; - this->buildBBoxHierarchy(); - // In order to avoid allocating a large canvas (particularly important for GPU), create one - // canvas that is a multiple of the tile size, and draw portions of the picture. - fLargeTileWidth = fXTilesPerLargeTile * this->getTileWidth(); - fLargeTileHeight = fYTilesPerLargeTile * this->getTileHeight(); - fCanvas.reset(this->INHERITED::setupCanvas(fLargeTileWidth, fLargeTileHeight)); - } - - bool CopyTilesRenderer::render(SkBitmap** out) { - int i = 0; - bool success = true; - SkBitmap dst; - for (int x = 0; x < this->getViewWidth(); x += fLargeTileWidth) { - for (int y = 0; y < this->getViewHeight(); y += fLargeTileHeight) { - SkAutoCanvasRestore autoRestore(fCanvas, true); - // Translate so that we draw the correct portion of the picture. - // Perform a postTranslate so that the scaleFactor does not interfere with the - // positioning. - SkMatrix mat(fCanvas->getTotalMatrix()); - mat.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); - fCanvas->setMatrix(mat); - // Draw the picture - if (fUseMultiPictureDraw) { - SkMultiPictureDraw mpd; - - mpd.add(fCanvas, fPicture); - - mpd.draw(); - } else { - fCanvas->drawPicture(fPicture); - } - // Now extract the picture into tiles - SkBitmap baseBitmap; - fCanvas->readPixels(SkIRect::MakeSize(fCanvas->getBaseLayerSize()), &baseBitmap); - SkIRect subset; - for (int tileY = 0; tileY < fLargeTileHeight; tileY += this->getTileHeight()) { - for (int tileX = 0; tileX < fLargeTileWidth; tileX += this->getTileWidth()) { - subset.set(tileX, tileY, tileX + this->getTileWidth(), - tileY + this->getTileHeight()); - SkDEBUGCODE(bool extracted =) - baseBitmap.extractSubset(&dst, subset); - SkASSERT(extracted); - if (!fWritePath.isEmpty()) { - // Similar to write() in PictureRenderer.cpp, but just encodes - // a bitmap directly. - // TODO: Share more common code with write() to do this, to properly - // write out the JSON summary, etc. - SkString pathWithNumber = SkOSPath::Join(fWritePath.c_str(), - fInputFilename.c_str()); - pathWithNumber.remove(pathWithNumber.size() - 4, 4); - pathWithNumber.appendf("%i.png", i++); - SkBitmap copy; -#if SK_SUPPORT_GPU - if (isUsingGpuDevice()) { - dst.pixelRef()->readPixels(©, &subset); - } else { -#endif - dst.copyTo(©); -#if SK_SUPPORT_GPU - } -#endif - success &= SkImageEncoder::EncodeFile(pathWithNumber.c_str(), copy, - SkImageEncoder::kPNG_Type, 100); - } - } - } - } - } - return success; - } - - SkString CopyTilesRenderer::getConfigNameInternal() { - return SkString("copy_tiles"); - } -} diff --git a/tools/CopyTilesRenderer.h b/tools/CopyTilesRenderer.h deleted file mode 100644 index 5ff4175eed..0000000000 --- a/tools/CopyTilesRenderer.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef CopyTilesRenderer_DEFINED -#define CopyTilesRenderer_DEFINED - -#include "PictureRenderer.h" -#include "SkTypes.h" - -struct GrContextOptions; -class SkPicture; -class SkString; - -namespace sk_tools { - /** - * PictureRenderer that draws the picture and then extracts it into tiles. For large pictures, - * it will divide the picture into large tiles and draw the picture once for each large tile. - */ - class CopyTilesRenderer : public TiledPictureRenderer { - - public: -#if SK_SUPPORT_GPU - CopyTilesRenderer(const GrContextOptions &opts, int x, int y); -#else - CopyTilesRenderer(int x, int y); -#endif - virtual void init(const SkPicture* pict, - const SkString* writePath, - const SkString* mismatchPath, - const SkString* inputFilename, - bool useChecksumBasedFilenames, - bool useMultiPictureDraw) override; - - /** - * Similar to TiledPictureRenderer, this will draw a PNG for each tile. However, the - * numbering (and actual tiles) will be different. - */ - bool render(SkBitmap** out) override; - - bool supportsTimingIndividualTiles() override { return false; } - - private: - int fXTilesPerLargeTile; - int fYTilesPerLargeTile; - - int fLargeTileWidth; - int fLargeTileHeight; - - SkString getConfigNameInternal() override; - - typedef TiledPictureRenderer INHERITED; - }; -} // sk_tools -#endif // CopyTilesRenderer_DEFINED diff --git a/tools/PictureBenchmark.cpp b/tools/PictureBenchmark.cpp deleted file mode 100644 index 84528e5744..0000000000 --- a/tools/PictureBenchmark.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "Timer.h" -#include "PictureBenchmark.h" -#include "SkCanvas.h" -#include "SkPicture.h" -#include "SkString.h" -#include "picture_utils.h" - -namespace sk_tools { - -PictureBenchmark::PictureBenchmark() - : fRepeats(1) - , fRenderer(nullptr) - , fTimerResult(TimerData::kAvg_Result) - , fTimerTypes(0) - , fTimeIndividualTiles(false) - , fPurgeDecodedTex(false) - , fWriter(nullptr) { -} - -PictureBenchmark::~PictureBenchmark() { - SkSafeUnref(fRenderer); -} - -void PictureBenchmark::setTimersToShow(bool wall, - bool truncatedWall, - bool cpu, - bool truncatedCpu, - bool gpu) { - fTimerTypes = 0; - fTimerTypes |= wall ? TimerData::kWall_Flag : 0; - fTimerTypes |= truncatedWall ? TimerData::kTruncatedWall_Flag : 0; - fTimerTypes |= cpu ? TimerData::kCpu_Flag : 0; - fTimerTypes |= truncatedCpu ? TimerData::kTruncatedCpu_Flag : 0; - fTimerTypes |= gpu ? TimerData::kGpu_Flag : 0; -} - -Timer* PictureBenchmark::setupTimer(bool useGLTimer) { -#if SK_SUPPORT_GPU - if (useGLTimer && fRenderer != nullptr && fRenderer->isUsingGpuDevice()) { - return new Timer(fRenderer->getGLContext()); - } -#endif - return new Timer(nullptr); -} - -PictureRenderer* PictureBenchmark::setRenderer(sk_tools::PictureRenderer* renderer) { - SkRefCnt_SafeAssign(fRenderer, renderer); - return renderer; -} - -void PictureBenchmark::run(SkPicture* pict, bool useMultiPictureDraw) { - SkASSERT(pict); - if (nullptr == pict) { - return; - } - - SkASSERT(fRenderer != nullptr); - if (nullptr == fRenderer) { - return; - } - - fRenderer->init(pict, nullptr, nullptr, nullptr, false, useMultiPictureDraw); - - // We throw this away to remove first time effects (such as paging in this program) - fRenderer->setup(); - - fRenderer->render(nullptr); - fRenderer->resetState(true); // flush, swapBuffers and Finish - - if (fPurgeDecodedTex) { - fRenderer->purgeTextures(); - } - - bool usingGpu = false; -#if SK_SUPPORT_GPU - usingGpu = fRenderer->isUsingGpuDevice(); -#endif - - uint32_t timerTypes = fTimerTypes; - if (!usingGpu) { - timerTypes &= ~TimerData::kGpu_Flag; - } - - SkString timeFormat; - if (TimerData::kPerIter_Result == fTimerResult) { - timeFormat = fRenderer->getPerIterTimeFormat(); - } else { - timeFormat = fRenderer->getNormalTimeFormat(); - } - - static const int kNumInnerLoops = 10; - int numOuterLoops = 1; - int numInnerLoops = fRepeats; - - if (TimerData::kPerIter_Result == fTimerResult && fRepeats > 1) { - // interpret this flag combination to mean: generate 'fRepeats' - // numbers by averaging each rendering 'kNumInnerLoops' times - numOuterLoops = fRepeats; - numInnerLoops = kNumInnerLoops; - } - - if (fTimeIndividualTiles) { - TiledPictureRenderer* tiledRenderer = fRenderer->getTiledRenderer(); - SkASSERT(tiledRenderer && tiledRenderer->supportsTimingIndividualTiles()); - if (nullptr == tiledRenderer || !tiledRenderer->supportsTimingIndividualTiles()) { - return; - } - int xTiles, yTiles; - if (!tiledRenderer->tileDimensions(xTiles, yTiles)) { - return; - } - - int x, y; - while (tiledRenderer->nextTile(x, y)) { - // There are two timers, which will behave slightly differently: - // 1) longRunningTimer, along with perTileTimerData, will time how long it takes to draw - // one tile fRepeats times, and take the average. As such, it will not respect the - // logPerIter or printMin options, since it does not know the time per iteration. It - // will also be unable to call flush() for each tile. - // The goal of this timer is to make up for a system timer that is not precise enough to - // measure the small amount of time it takes to draw one tile once. - // - // 2) perTileTimer, along with perTileTimerData, will record each run separately, and - // then take the average. As such, it supports logPerIter and printMin options. - // - // Although "legal", having two gpu timers running at the same time - // seems to cause problems (i.e., INVALID_OPERATIONs) on several - // platforms. To work around this, we disable the gpu timer on the - // long running timer. - SkAutoTDelete<Timer> longRunningTimer(this->setupTimer()); - TimerData longRunningTimerData(numOuterLoops); - - for (int outer = 0; outer < numOuterLoops; ++outer) { - SkAutoTDelete<Timer> perTileTimer(this->setupTimer(false)); - TimerData perTileTimerData(numInnerLoops); - - longRunningTimer->start(); - for (int inner = 0; inner < numInnerLoops; ++inner) { - perTileTimer->start(); - tiledRenderer->drawCurrentTile(); - perTileTimer->truncatedEnd(); - tiledRenderer->resetState(false); // flush & swapBuffers, but don't Finish - perTileTimer->end(); - SkAssertResult(perTileTimerData.appendTimes(perTileTimer.get())); - - if (fPurgeDecodedTex) { - fRenderer->purgeTextures(); - } - } - longRunningTimer->truncatedEnd(); - tiledRenderer->resetState(true); // flush, swapBuffers and Finish - longRunningTimer->end(); - SkAssertResult(longRunningTimerData.appendTimes(longRunningTimer.get())); - } - - fWriter->logRenderer(tiledRenderer); - fWriter->tileMeta(x, y, xTiles, yTiles); - - // TODO(borenet): Turn off per-iteration tile time reporting for now. - // Avoiding logging the time for every iteration for each tile cuts - // down on data file size by a significant amount. Re-enable this once - // we're loading the bench data directly into a data store and are no - // longer generating SVG graphs. -#if 0 - fWriter->tileData( - &perTileTimerData, - timeFormat.c_str(), - fTimerResult, - timerTypes); -#endif - - if (fPurgeDecodedTex) { - fWriter->addTileFlag(PictureResultsWriter::kPurging); - } - fWriter->addTileFlag(PictureResultsWriter::kAvg); - fWriter->tileData( - &longRunningTimerData, - tiledRenderer->getNormalTimeFormat().c_str(), - TimerData::kAvg_Result, - timerTypes, - numInnerLoops); - } - } else { - SkAutoTDelete<Timer> longRunningTimer(this->setupTimer()); - TimerData longRunningTimerData(numOuterLoops); - - for (int outer = 0; outer < numOuterLoops; ++outer) { - SkAutoTDelete<Timer> perRunTimer(this->setupTimer(false)); - TimerData perRunTimerData(numInnerLoops); - - longRunningTimer->start(); - for (int inner = 0; inner < numInnerLoops; ++inner) { - fRenderer->setup(); - - perRunTimer->start(); - fRenderer->render(nullptr); - perRunTimer->truncatedEnd(); - fRenderer->resetState(false); // flush & swapBuffers, but don't Finish - perRunTimer->end(); - - SkAssertResult(perRunTimerData.appendTimes(perRunTimer.get())); - - if (fPurgeDecodedTex) { - fRenderer->purgeTextures(); - } - } - longRunningTimer->truncatedEnd(); - fRenderer->resetState(true); // flush, swapBuffers and Finish - longRunningTimer->end(); - SkAssertResult(longRunningTimerData.appendTimes(longRunningTimer.get())); - } - - fWriter->logRenderer(fRenderer); - if (fPurgeDecodedTex) { - fWriter->addTileFlag(PictureResultsWriter::kPurging); - } - - // Beware - since the per-run-timer doesn't ever include a glFinish it can - // report a lower time then the long-running-timer -#if 0 - fWriter->tileData( - &perRunTimerData, - timeFormat.c_str(), - fTimerResult, - timerTypes); -#else - fWriter->tileData( - &longRunningTimerData, - timeFormat.c_str(), - fTimerResult, - timerTypes, - numInnerLoops); -#endif - } - - fRenderer->end(); -} - -} diff --git a/tools/PictureBenchmark.h b/tools/PictureBenchmark.h deleted file mode 100644 index 99eca6bcc0..0000000000 --- a/tools/PictureBenchmark.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef PictureBenchmark_DEFINED -#define PictureBenchmark_DEFINED - -#include "PictureRenderer.h" -#include "PictureResultsWriter.h" -#include "SkTypes.h" -#include "TimerData.h" - -class SkPicture; -class Timer; - -namespace sk_tools { - -class PictureBenchmark { -public: - PictureBenchmark(); - - ~PictureBenchmark(); - - /** - * Draw the provided SkPicture fRepeats times while collecting timing data, and log the output - * via fWriter. - */ - void run(SkPicture* pict, bool useMultiPictureDraw); - - void setRepeats(int repeats) { - fRepeats = repeats; - } - - /** - * If true, tells run to log separate timing data for each individual tile. Each tile will be - * drawn fRepeats times. Requires the PictureRenderer set by setRenderer to be a - * TiledPictureRenderer. - */ - void setTimeIndividualTiles(bool indiv) { fTimeIndividualTiles = indiv; } - bool timeIndividualTiles() const { return fTimeIndividualTiles; } - - void setPurgeDecodedTex(bool purgeDecodedTex) { fPurgeDecodedTex = purgeDecodedTex; } - bool purgeDecodedText() const { return fPurgeDecodedTex; } - - PictureRenderer* setRenderer(PictureRenderer*); - PictureRenderer* renderer() { return fRenderer; } - - void setTimerResultType(TimerData::Result resultType) { fTimerResult = resultType; } - - void setTimersToShow(bool wall, bool truncatedWall, bool cpu, bool truncatedCpu, bool gpu); - - void setWriter(PictureResultsWriter* writer) { fWriter = writer; } - -private: - int fRepeats; - PictureRenderer* fRenderer; - TimerData::Result fTimerResult; - uint32_t fTimerTypes; // bitfield of TimerData::TimerFlags values - bool fTimeIndividualTiles; - bool fPurgeDecodedTex; - - PictureResultsWriter* fWriter; - - Timer* setupTimer(bool useGLTimer = true); -}; - -} - -#endif // PictureBenchmark_DEFINED diff --git a/tools/PictureRenderer.cpp b/tools/PictureRenderer.cpp index 19ee7b5f2a..c550b6eefb 100644 --- a/tools/PictureRenderer.cpp +++ b/tools/PictureRenderer.cpp @@ -283,87 +283,6 @@ void PictureRenderer::purgeTextures() { #endif } -/** - * Write the canvas to an image file and/or JSON summary. - * - * @param canvas Must be non-null. Canvas to be written to a file. - * @param writePath If nonempty, write the binary image to a file within this directory. - * @param mismatchPath If nonempty, write the binary image to a file within this directory, - * but only if the image does not match expectations. - * @param inputFilename If we are writing out a binary image, use this to build its filename. - * @param jsonSummaryPtr If not null, add image results (checksum) to this summary. - * @param useChecksumBasedFilenames If true, use checksum-based filenames when writing to disk. - * @param tileNumberPtr If not null, which tile number this image contains. - * - * @return bool True if the operation completed successfully. - */ -static bool write(SkCanvas* canvas, const SkString& writePath, const SkString& mismatchPath, - const SkString& inputFilename, ImageResultsAndExpectations *jsonSummaryPtr, - bool useChecksumBasedFilenames, const int* tileNumberPtr=nullptr) { - SkASSERT(canvas != nullptr); - if (nullptr == canvas) { - return false; - } - - SkBitmap bitmap; - SkISize size = canvas->getDeviceSize(); - setup_bitmap(&bitmap, size.width(), size.height()); - - canvas->readPixels(&bitmap, 0, 0); - force_all_opaque(bitmap); - BitmapAndDigest bitmapAndDigest(bitmap); - - SkString escapedInputFilename(inputFilename); - replace_char(&escapedInputFilename, '.', '_'); - - // TODO(epoger): what about including the config type within outputFilename? That way, - // we could combine results of different config types without conflicting filenames. - SkString outputFilename; - const char *outputSubdirPtr = nullptr; - if (useChecksumBasedFilenames) { - ImageDigest *imageDigestPtr = bitmapAndDigest.getImageDigestPtr(); - outputSubdirPtr = escapedInputFilename.c_str(); - outputFilename.set(imageDigestPtr->getHashType()); - outputFilename.append("_"); - outputFilename.appendU64(imageDigestPtr->getHashValue()); - } else { - outputFilename.set(escapedInputFilename); - if (tileNumberPtr) { - outputFilename.append("-tile"); - outputFilename.appendS32(*tileNumberPtr); - } - } - outputFilename.append(".png"); - - if (jsonSummaryPtr) { - ImageDigest *imageDigestPtr = bitmapAndDigest.getImageDigestPtr(); - SkString outputRelativePath; - if (outputSubdirPtr) { - outputRelativePath.set(outputSubdirPtr); - outputRelativePath.append("/"); // always use "/", even on Windows - outputRelativePath.append(outputFilename); - } else { - outputRelativePath.set(outputFilename); - } - - jsonSummaryPtr->add(inputFilename.c_str(), outputRelativePath.c_str(), - *imageDigestPtr, tileNumberPtr); - if (!mismatchPath.isEmpty() && - !jsonSummaryPtr->getExpectation(inputFilename.c_str(), - tileNumberPtr).matches(*imageDigestPtr)) { - if (!write_bitmap_to_disk(bitmap, mismatchPath, outputSubdirPtr, outputFilename)) { - return false; - } - } - } - - if (writePath.isEmpty()) { - return true; - } else { - return write_bitmap_to_disk(bitmap, writePath, outputSubdirPtr, outputFilename); - } -} - /////////////////////////////////////////////////////////////////////////////////////////////// SkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) { @@ -417,12 +336,7 @@ bool PipePictureRenderer::render(SkBitmap** out) { SkScalarCeilToInt(fPicture->cullRect().height())); fCanvas->readPixels(*out, 0, 0); } - if (fEnableWrites) { - return write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr, - fUseChecksumBasedFilenames); - } else { - return true; - } + return true; } SkString PipePictureRenderer::getConfigNameInternal() { @@ -462,12 +376,7 @@ bool SimplePictureRenderer::render(SkBitmap** out) { SkScalarCeilToInt(fPicture->cullRect().height())); fCanvas->readPixels(*out, 0, 0); } - if (fEnableWrites) { - return write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr, - fUseChecksumBasedFilenames); - } else { - return true; - } + return true; } SkString SimplePictureRenderer::getConfigNameInternal() { @@ -674,10 +583,6 @@ bool TiledPictureRenderer::postRender(SkCanvas* canvas, const SkIRect& tileRect, int tileNumber) { bool success = true; - if (fEnableWrites) { - success &= write(canvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr, - fUseChecksumBasedFilenames, &tileNumber); - } if (out) { if (canvas->readPixels(tempBM, 0, 0)) { // Add this tile to the entire bitmap. diff --git a/tools/PictureRenderer.h b/tools/PictureRenderer.h index e935f40170..6197fb0644 100644 --- a/tools/PictureRenderer.h +++ b/tools/PictureRenderer.h @@ -26,8 +26,6 @@ #include "GrContext.h" #endif -#include "image_expectations.h" - struct GrContextOptions; class SkBitmap; class SkCanvas; @@ -102,14 +100,6 @@ public: bool useMultiPictureDraw); /** - * TODO(epoger): Temporary hack, while we work on http://skbug.com/2584 ('bench_pictures is - * timing reading pixels and writing json files'), such that: - * - render_pictures can call this method and continue to work - * - any other callers (bench_pictures) will skip calls to write() by default - */ - void enableWrites() { fEnableWrites = true; } - - /** * Set the viewport so that only the portion listed gets drawn. */ void setViewport(SkISize size) { fViewport = size; } @@ -251,10 +241,6 @@ public: BBoxHierarchyType getBBoxHierarchyType() { return fBBoxHierarchyType; } - void setJsonSummaryPtr(ImageResultsAndExpectations* jsonSummaryPtr) { - fJsonSummaryPtr = jsonSummaryPtr; - } - bool isUsingBitmapDevice() { return kBitmap_DeviceType == fDeviceType; } @@ -444,9 +430,7 @@ public: #else PictureRenderer() #endif - : fJsonSummaryPtr(nullptr) - , fDeviceType(kBitmap_DeviceType) - , fEnableWrites(false) + : fDeviceType(kBitmap_DeviceType) , fBBoxHierarchyType(kNone_BBoxHierarchyType) , fHasDrawFilters(false) , fScaleFactor(SK_Scalar1) @@ -472,9 +456,7 @@ protected: SkAutoTUnref<const SkPicture> fPicture; bool fUseChecksumBasedFilenames; bool fUseMultiPictureDraw; - ImageResultsAndExpectations* fJsonSummaryPtr; SkDeviceTypes fDeviceType; - bool fEnableWrites; BBoxHierarchyType fBBoxHierarchyType; bool fHasDrawFilters; DrawFilterFlags fDrawFilters[SkDrawFilter::kTypeCount]; diff --git a/tools/PictureRenderingFlags.cpp b/tools/PictureRenderingFlags.cpp deleted file mode 100644 index ea316843a9..0000000000 --- a/tools/PictureRenderingFlags.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright 2013 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "PictureRenderingFlags.h" - -#include "CopyTilesRenderer.h" -#if SK_SUPPORT_GPU -#include "GrContextOptions.h" -#endif -#include "PictureRenderer.h" -#include "picture_utils.h" -#include "SkCommandLineFlags.h" -#include "SkData.h" -#include "SkImage.h" -#include "SkImageDecoder.h" -#include "SkString.h" - -#include <stdlib.h> - -// Alphabetized list of flags used by this file or bench_ and render_pictures. -DEFINE_string(bbh, "none", "bbhType [width height]: Set the bounding box hierarchy type to " - "be used. Accepted values are: none, rtree, grid. " - "Not compatible with --pipe. With value " - "'grid', width and height must be specified. 'grid' can " - "only be used with modes tile, record, and " - "playbackCreation."); - - -#if SK_SUPPORT_GPU -static const char kGpuAPINameGL[] = "gl"; -static const char kGpuAPINameGLES[] = "gles"; -#define GPU_CONFIG_STRING "|gpu|msaa4|msaa16|nvprmsaa4|nvprmsaa16|gpudft" -#else -#define GPU_CONFIG_STRING "" -#endif -#if SK_ANGLE -#define ANGLE_CONFIG_STRING "|angle" -#else -#define ANGLE_CONFIG_STRING "" -#endif -#if SK_COMMAND_BUFFER -#define COMMAND_BUFFER_CONFIG_STRING "|commandbuffer" -#else -#define COMMAND_BUFFER_CONFIG_STRING "" -#endif -#if SK_MESA -#define MESA_CONFIG_STRING "|mesa" -#else -#define MESA_CONFIG_STRING "" -#endif - -// Although this config does not support all the same options as gm, the names should be kept -// consistent. -DEFINE_string(config, "8888", "[" - "8888" GPU_CONFIG_STRING ANGLE_CONFIG_STRING COMMAND_BUFFER_CONFIG_STRING MESA_CONFIG_STRING - "]: Use the corresponding config."); - -DEFINE_bool(deferImageDecoding, false, "Defer decoding until drawing images. " - "Has no effect if the provided skp does not have its images encoded."); -DEFINE_string(mode, "simple", "Run in the corresponding mode:\n" - "simple: Simple rendering.\n" - "tile width height: Use tiles with the given dimensions or percentages.\n" - "pow2tile minWidth height: Use tiles with widths that are all a power\n" - "\tof two such that they minimize the amount of wasted tile space.\n" - "\tminWidth must be a power of two.\n" - "copyTile width height: Draw the picture, then copy into tiles. If the\n" - "\tpicture is large enough, it is broken into larger tiles to avoid\n" - "\tcreating a large canvas.\n" -// TODO: If bench_pictures and render_pictures were two separate targets, we could use build flags -// to determine which modes to display. - "record: (Only in bench_pictures) Time recording from a picture to a new\n" - "\tpicture.\n" - "playbackCreation: (Only in bench_pictures) Time creation of the \n" - "\tSkPicturePlayback.\n" - "rerecord: (Only in render_pictures) Record the picture as a new skp,\n" - "\twith the bitmaps PNG encoded.\n"); -DEFINE_bool(pipe, false, "Use SkGPipe rendering. Currently incompatible with \"mode\"."); -DEFINE_string2(readPath, r, "", "skp files or directories of skp files to process."); -DEFINE_double(scale, 1, "Set the scale factor."); -DEFINE_string(tiles, "", "Used with --mode copyTile to specify number of tiles per larger tile " - "in the x and y directions."); -DEFINE_string(viewport, "", "width height: Set the viewport."); -#if SK_SUPPORT_GPU -DEFINE_string(gpuAPI, "", "Force use of specific gpu API. Using \"gl\" " - "forces OpenGL API. Using \"gles\" forces OpenGL ES API. " - "Defaults to empty string, which selects the API native to the " - "system."); -DEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling back to " - "software path rendering."); -#endif - -sk_tools::PictureRenderer* parseRenderer(SkString& error, PictureTool tool) { - error.reset(); - - bool useTiles = false; - const char* widthString = nullptr; - const char* heightString = nullptr; - bool isPowerOf2Mode = false; - bool isCopyMode = false; - const char* mode = nullptr; - -#if SK_SUPPORT_GPU - GrContextOptions grContextOpts; - grContextOpts.fDrawPathToCompressedTexture = FLAGS_gpuCompressAlphaMasks; - #define RENDERER_ARGS (grContextOpts) -#else - #define RENDERER_ARGS () -#endif - - SkAutoTUnref<sk_tools::PictureRenderer> renderer; - if (FLAGS_mode.count() >= 1) { - mode = FLAGS_mode[0]; - if (0 == strcmp(mode, "record")) { - renderer.reset(new sk_tools::RecordPictureRenderer RENDERER_ARGS); - } else if (0 == strcmp(mode, "tile") || 0 == strcmp(mode, "pow2tile") - || 0 == strcmp(mode, "copyTile")) { - useTiles = true; - - if (0 == strcmp(mode, "pow2tile")) { - isPowerOf2Mode = true; - } else if (0 == strcmp(mode, "copyTile")) { - isCopyMode = true; - } - - if (FLAGS_mode.count() < 2) { - error.printf("Missing width for --mode %s\n", mode); - return nullptr; - } - - widthString = FLAGS_mode[1]; - if (FLAGS_mode.count() < 3) { - error.printf("Missing height for --mode %s\n", mode); - return nullptr; - } - - heightString = FLAGS_mode[2]; - } else if (0 == strcmp(mode, "playbackCreation") && kBench_PictureTool == tool) { - renderer.reset(new sk_tools::PlaybackCreationRenderer RENDERER_ARGS); - // undocumented - } else if (0 == strcmp(mode, "rerecord") && kRender_PictureTool == tool) { - renderer.reset(new sk_tools::RecordPictureRenderer RENDERER_ARGS); - } else if (0 == strcmp(mode, "simple")) { - // Allow 'mode' to be set to 'simple', but do not create a renderer, so we can - // ensure that pipe does not override a mode besides simple. The renderer will - // be created below. - } else { - error.printf("%s is not a valid mode for --mode\n", mode); - return nullptr; - } - } - - if (useTiles) { - SkASSERT(nullptr == renderer); - SkAutoTUnref<sk_tools::TiledPictureRenderer> tiledRenderer; - if (isCopyMode) { - int xTiles = -1; - int yTiles = -1; - if (FLAGS_tiles.count() > 0) { - if (FLAGS_tiles.count() != 2) { - error.printf("--tiles requires an x value and a y value.\n"); - return nullptr; - } - xTiles = atoi(FLAGS_tiles[0]); - yTiles = atoi(FLAGS_tiles[1]); - } - - int x, y; - if (xTiles != -1 && yTiles != -1) { - x = xTiles; - y = yTiles; - if (x <= 0 || y <= 0) { - error.printf("--tiles must be given values > 0\n"); - return nullptr; - } - } else { - x = y = 4; - } -#if SK_SUPPORT_GPU - tiledRenderer.reset(new sk_tools::CopyTilesRenderer(grContextOpts, x, y)); -#else - tiledRenderer.reset(new sk_tools::CopyTilesRenderer(x, y)); -#endif - } else { - tiledRenderer.reset(new sk_tools::TiledPictureRenderer RENDERER_ARGS); - } - - if (isPowerOf2Mode) { - int minWidth = atoi(widthString); - if (!SkIsPow2(minWidth) || minWidth < 0) { - SkString err; - error.printf("-mode %s must be given a width" - " value that is a power of two\n", mode); - return nullptr; - } - tiledRenderer->setTileMinPowerOf2Width(minWidth); - } else if (sk_tools::is_percentage(widthString)) { - if (isCopyMode) { - error.printf("--mode %s does not support percentages.\n", mode); - return nullptr; - } - tiledRenderer->setTileWidthPercentage(atof(widthString)); - if (!(tiledRenderer->getTileWidthPercentage() > 0)) { - error.printf("--mode %s must be given a width percentage > 0\n", mode); - return nullptr; - } - } else { - tiledRenderer->setTileWidth(atoi(widthString)); - if (!(tiledRenderer->getTileWidth() > 0)) { - error.printf("--mode %s must be given a width > 0\n", mode); - return nullptr; - } - } - - if (sk_tools::is_percentage(heightString)) { - if (isCopyMode) { - error.printf("--mode %s does not support percentages.\n", mode); - return nullptr; - } - tiledRenderer->setTileHeightPercentage(atof(heightString)); - if (!(tiledRenderer->getTileHeightPercentage() > 0)) { - error.printf("--mode %s must be given a height percentage > 0\n", mode); - return nullptr; - } - } else { - tiledRenderer->setTileHeight(atoi(heightString)); - if (!(tiledRenderer->getTileHeight() > 0)) { - SkString err; - error.printf("--mode %s must be given a height > 0\n", mode); - return nullptr; - } - } - - renderer.reset(tiledRenderer.detach()); - if (FLAGS_pipe) { - error.printf("Pipe rendering is currently not compatible with tiling.\n" - "Turning off pipe.\n"); - } - - } else { // useTiles - if (FLAGS_pipe) { - if (renderer != nullptr) { - error.printf("Pipe is incompatible with other modes.\n"); - return nullptr; - } - renderer.reset(new sk_tools::PipePictureRenderer RENDERER_ARGS); - } - } - - if (nullptr == renderer) { - renderer.reset(new sk_tools::SimplePictureRenderer RENDERER_ARGS); - } - - if (FLAGS_viewport.count() > 0) { - if (FLAGS_viewport.count() != 2) { - error.printf("--viewport requires a width and a height.\n"); - return nullptr; - } - SkISize viewport; - viewport.fWidth = atoi(FLAGS_viewport[0]); - viewport.fHeight = atoi(FLAGS_viewport[1]); - renderer->setViewport(viewport); - } - - sk_tools::PictureRenderer::SkDeviceTypes deviceType = - sk_tools::PictureRenderer::kBitmap_DeviceType; -#if SK_SUPPORT_GPU - GrGLStandard gpuAPI = kNone_GrGLStandard; - if (1 == FLAGS_gpuAPI.count()) { - if (FLAGS_gpuAPI.contains(kGpuAPINameGL)) { - gpuAPI = kGL_GrGLStandard; - } else if (FLAGS_gpuAPI.contains(kGpuAPINameGLES)) { - gpuAPI = kGLES_GrGLStandard; - } else { - error.printf("--gpuAPI invalid api value.\n"); - return nullptr; - } - } else if (FLAGS_gpuAPI.count() > 1) { - error.printf("--gpuAPI invalid api value.\n"); - return nullptr; - } - - int sampleCount = 0; - bool useDFText = false; -#endif - if (FLAGS_config.count() > 0) { - if (0 == strcmp(FLAGS_config[0], "8888")) { - deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType; - } -#if SK_SUPPORT_GPU - else if (0 == strcmp(FLAGS_config[0], "gpu")) { - deviceType = sk_tools::PictureRenderer::kGPU_DeviceType; - } - else if (0 == strcmp(FLAGS_config[0], "msaa4")) { - deviceType = sk_tools::PictureRenderer::kGPU_DeviceType; - sampleCount = 4; - } - else if (0 == strcmp(FLAGS_config[0], "msaa16")) { - deviceType = sk_tools::PictureRenderer::kGPU_DeviceType; - sampleCount = 16; - } - else if (0 == strcmp(FLAGS_config[0], "nvprmsaa4")) { - deviceType = sk_tools::PictureRenderer::kNVPR_DeviceType; - sampleCount = 4; - } - else if (0 == strcmp(FLAGS_config[0], "nvprmsaa16")) { - deviceType = sk_tools::PictureRenderer::kNVPR_DeviceType; - sampleCount = 16; - } - else if (0 == strcmp(FLAGS_config[0], "gpudft")) { - deviceType = sk_tools::PictureRenderer::kGPU_DeviceType; - useDFText = true; - } -#if SK_ANGLE - else if (0 == strcmp(FLAGS_config[0], "angle")) { - deviceType = sk_tools::PictureRenderer::kAngle_DeviceType; - } -#endif -#if SK_COMMAND_BUFFER - else if (0 == strcmp(FLAGS_config[0], "commandbuffer")) { - deviceType = sk_tools::PictureRenderer::kCommandBuffer_DeviceType; - } -#endif -#if SK_MESA - else if (0 == strcmp(FLAGS_config[0], "mesa")) { - deviceType = sk_tools::PictureRenderer::kMesa_DeviceType; - } -#endif -#endif - else { - error.printf("%s is not a valid mode for --config\n", FLAGS_config[0]); - return nullptr; - } -#if SK_SUPPORT_GPU - if (!renderer->setDeviceType(deviceType, gpuAPI)) { -#else - if (!renderer->setDeviceType(deviceType)) { -#endif - error.printf("Could not create backend for --config %s\n", FLAGS_config[0]); - return nullptr; - } -#if SK_SUPPORT_GPU - renderer->setSampleCount(sampleCount); - renderer->setUseDFText(useDFText); -#endif - } - - - sk_tools::PictureRenderer::BBoxHierarchyType bbhType - = sk_tools::PictureRenderer::kNone_BBoxHierarchyType; - if (FLAGS_bbh.count() > 0) { - const char* type = FLAGS_bbh[0]; - if (0 == strcmp(type, "none")) { - bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType; - } else if (0 == strcmp(type, "rtree")) { - bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType; - } else { - error.printf("%s is not a valid value for --bbhType\n", type); - return nullptr; - } - if (FLAGS_pipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) { - error.printf("--pipe and --bbh cannot be used together\n"); - return nullptr; - } - } - renderer->setBBoxHierarchyType(bbhType); - renderer->setScaleFactor(SkDoubleToScalar(FLAGS_scale)); - - return renderer.detach(); -} diff --git a/tools/PictureRenderingFlags.h b/tools/PictureRenderingFlags.h deleted file mode 100644 index 9f0ee79432..0000000000 --- a/tools/PictureRenderingFlags.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2013 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef PICTURE_RENDERING_FLAGS -#define PICTURE_RENDERING_FLAGS - -class SkString; - -namespace sk_tools { - class PictureRenderer; -} - -enum PictureTool { - kBench_PictureTool, - kRender_PictureTool, -}; - -/** - * Uses SkCommandLineFlags to parse the command line, and returns a PictureRenderer - * reflecting the flags used. Assumes that SkCommandLineFlags::Parse has - * been called. - * @param error If there is an error or warning, it will be stored in error. - * @param tool Which tool is being used. - * @return PictureRenderer A PictureRenderer with the settings specified - * on the command line, or nullptr if the command line is invalid. - */ -sk_tools::PictureRenderer* parseRenderer(SkString& error, PictureTool tool); - -#endif // PICTURE_RENDERING_FLAGS diff --git a/tools/PictureResultsWriter.h b/tools/PictureResultsWriter.h deleted file mode 100644 index 8e606dceeb..0000000000 --- a/tools/PictureResultsWriter.h +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Classes for writing out bench results in various formats. - */ - -#ifndef SkPictureResultsWriter_DEFINED -#define SkPictureResultsWriter_DEFINED - - -#include "PictureRenderer.h" -#include "BenchLogger.h" -#include "ResultsWriter.h" -#include "SkJSONCPP.h" -#include "SkStream.h" -#include "SkString.h" -#include "SkTArray.h" -#include "TimerData.h" - -#include <stdlib.h> - -/** - * Base class for writing picture bench results. - */ -class PictureResultsWriter : SkNoncopyable { -public: - enum TileFlags {kPurging, kAvg}; - - PictureResultsWriter() {} - virtual ~PictureResultsWriter() {} - - virtual void bench(const char name[], int32_t x, int32_t y) = 0; - virtual void logRenderer(sk_tools::PictureRenderer *pr) = 0; - virtual void tileMeta(int x, int y, int tx, int ty) = 0; - virtual void addTileFlag(PictureResultsWriter::TileFlags flag) = 0; - virtual void tileData( - TimerData* data, - const char format[], - const TimerData::Result result, - uint32_t timerTypes, - int numInnerLoops = 1) = 0; - virtual void end() = 0; -}; - -/** - * This class allows bench data to be piped into multiple - * PictureResultWriter classes. It does not own any classes - * passed to it, so the owner is required to manage any classes - * passed to PictureResultsMultiWriter */ -class PictureResultsMultiWriter : public PictureResultsWriter { -public: - PictureResultsMultiWriter() - : fWriters() {} - void add(PictureResultsWriter* newWriter) { - fWriters.push_back(newWriter); - } - virtual ~PictureResultsMultiWriter() {} - void bench(const char name[], int32_t x, int32_t y) override { - for(int i=0; i<fWriters.count(); ++i) { - fWriters[i]->bench(name, x, y); - } - } - void logRenderer(sk_tools::PictureRenderer *pr) override { - for(int i=0; i<fWriters.count(); ++i) { - fWriters[i]->logRenderer(pr); - } - } - void tileMeta(int x, int y, int tx, int ty) override { - for(int i=0; i<fWriters.count(); ++i) { - fWriters[i]->tileMeta(x, y, tx, ty); - } - } - void addTileFlag(PictureResultsWriter::TileFlags flag) override { - for(int i=0; i<fWriters.count(); ++i) { - fWriters[i]->addTileFlag(flag); - } - } - virtual void tileData( - TimerData* data, - const char format[], - const TimerData::Result result, - uint32_t timerTypes, - int numInnerLoops = 1) override { - for(int i=0; i<fWriters.count(); ++i) { - fWriters[i]->tileData(data, format, result, timerTypes, - numInnerLoops); - } - } - void end() override { - for(int i=0; i<fWriters.count(); ++i) { - fWriters[i]->end(); - } - } -private: - SkTArray<PictureResultsWriter*> fWriters; -}; - -/** - * Writes to BenchLogger to mimic original behavior - */ -class PictureResultsLoggerWriter : public PictureResultsWriter { -private: - void logProgress(const char str[]) { - if(fLogger != nullptr) { - fLogger->logProgress(str); - } - } -public: - PictureResultsLoggerWriter(BenchLogger* log) - : fLogger(log), fCurrentLine() {} - void bench(const char name[], int32_t x, int32_t y) override { - SkString result; - result.printf("running bench [%i %i] %s ", x, y, name); - this->logProgress(result.c_str()); - } - void logRenderer(sk_tools::PictureRenderer* renderer) override { - fCurrentLine = renderer->getConfigName(); - } - void tileMeta(int x, int y, int tx, int ty) override { - fCurrentLine.appendf(": tile [%i,%i] out of [%i,%i]", x, y, tx, ty); - } - void addTileFlag(PictureResultsWriter::TileFlags flag) override { - if(flag == PictureResultsWriter::kPurging) { - fCurrentLine.append(" <withPurging>"); - } else if(flag == PictureResultsWriter::kAvg) { - fCurrentLine.append(" <averaged>"); - } - } - virtual void tileData( - TimerData* data, - const char format[], - const TimerData::Result result, - uint32_t timerTypes, - int numInnerLoops = 1) override { - SkString results = data->getResult(format, result, - fCurrentLine.c_str(), timerTypes, numInnerLoops); - results.append("\n"); - this->logProgress(results.c_str()); - } - void end() override {} -private: - BenchLogger* fLogger; - SkString fCurrentLine; -}; - -/** - * This PictureResultsWriter collects data in a JSON node - * - * The format is something like - * { - * benches: [ - * { - * name: "Name_of_test" - * tilesets: [ - * { - * name: "Name of the configuration" - * tiles: [ - * { - * flags: { - * purging: true //Flags for the current tile - * // are put here - * } - * data: { - * wsecs: [....] //Actual data ends up here - * } - * } - * ] - * } - * ] - * } - * ] - * }*/ - -class PictureJSONResultsWriter : public PictureResultsWriter { -public: - PictureJSONResultsWriter(const char filename[], - const char builderName[], - int buildNumber, - int timestamp, - const char gitHash[], - int gitNumber) - : fStream(filename) { - fBuilderName = SkString(builderName); - fBuildNumber = buildNumber; - fTimestamp = timestamp; - fGitHash = SkString(gitHash); - fGitNumber = gitNumber; - fBuilderData = this->makeBuilderJson(); - } - - void bench(const char name[], int32_t x, int32_t y) override { - fBenchName = SkString(name); - } - void logRenderer(sk_tools::PictureRenderer* pr) override { - fParams = pr->getJSONConfig(); - fConfigString = pr->getConfigName(); - } - // Apparently tiles aren't used, so tileMeta is empty - void tileMeta(int x, int y, int tx, int ty) override {} - // Flags aren't used, so addTileFlag is empty - void addTileFlag(PictureResultsWriter::TileFlags flag) override {} - virtual void tileData( - TimerData* data, - const char format[], - const TimerData::Result result, - uint32_t timerTypes, - int numInnerLoops = 1) override { - Json::Value newData = data->getJSON(timerTypes, result, numInnerLoops); - Json::Value combinedParams(fBuilderData); - for(Json::ValueIterator iter = fParams.begin(); iter != fParams.end(); - iter++) { - combinedParams[iter.key().asString()]= *iter; - } - // For each set of timer data - for(Json::ValueIterator iter = newData.begin(); iter != newData.end(); - iter++) { - Json::Value data; - data["buildNumber"] = fBuildNumber; - data["timestamp"] = fTimestamp; - data["gitHash"] = fGitHash.c_str(); - data["gitNumber"] = fGitNumber; - data["isTrybot"] = fBuilderName.endsWith("Trybot"); - - data["params"] = combinedParams; - data["params"]["benchName"] = fBenchName.c_str(); - - // Not including skpSize because that's deprecated? - data["key"] = this->makeKey(iter.key().asString().c_str()).c_str(); - // Get the data - SkTArray<double> times; - Json::Value val = *iter; - for(Json::ValueIterator vals = val.begin(); vals != val.end(); - vals++) { - times.push_back((*vals).asDouble()); - } - qsort(static_cast<void*>(times.begin()), times.count(), - sizeof(double), PictureJSONResultsWriter::CompareDoubles); - data["value"] = times[static_cast<int>(times.count() * 0.25f)]; - data["params"]["measurementType"] = iter.key().asString(); - fStream.writeText(Json::FastWriter().write(data).c_str()); - } - } - void end() override { - fStream.flush(); - } -private: - Json::Value makeBuilderJson() const { - static const int kNumKeys = 6; - static const char* kKeys[kNumKeys] = { - "role", "os", "model", "gpu", "arch", "configuration"}; - Json::Value builderData; - - if (!fBuilderName.isEmpty()) { - SkTArray<SkString> splitBuilder; - SkStrSplit(fBuilderName.c_str(), "-", &splitBuilder); - SkASSERT(splitBuilder.count() >= kNumKeys); - for (int i = 0; i < kNumKeys && i < splitBuilder.count(); ++i) { - builderData[kKeys[i]] = splitBuilder[i].c_str(); - } - builderData["builderName"] = fBuilderName.c_str(); - if (kNumKeys < splitBuilder.count()) { - SkString extras; - for (int i = kNumKeys; i < splitBuilder.count(); ++i) { - extras.append(splitBuilder[i]); - if (i != splitBuilder.count() - 1) { - extras.append("-"); - } - } - builderData["badParams"] = extras.c_str(); - } - } - return builderData; - } - - static int CompareDoubles(const void* p1, const void* p2) { - if(*static_cast<const double*>(p1) < *static_cast<const double*>(p2)) { - return -1; - } else if(*static_cast<const double*>(p1) == - *static_cast<const double*>(p2)) { - return 0; - } else { - return 1; - } - } - SkString makeKey(const char measurementType[]) const { - SkString tmp(fBuilderName); - tmp.append("_"); - tmp.append(fBenchName); - tmp.append("_"); - tmp.append(fConfigString); - tmp.append("_"); - tmp.append(measurementType); - return tmp; - } - - SkFILEWStream fStream; - Json::Value fBuilderData; - SkString fBenchName; - Json::Value fParams; - - SkString fConfigString; - SkString fBuilderName; - int fBuildNumber; - int fTimestamp; - SkString fGitHash; - int fGitNumber; -}; - -#endif diff --git a/tools/bench_pictures.cfg b/tools/bench_pictures.cfg deleted file mode 100644 index ab049e3163..0000000000 --- a/tools/bench_pictures.cfg +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - - -""" -This file defines the configurations in which bench_pictures should be run -on various platforms. The buildbots read these configurations from the -bench_pictures_cfg dictionary. Everything else in this file exists to help in -constructing that dictionary. - -This code is executed directly on the buildbot so that convenient things like -variables and loops can be used to avoid unnecessary verbosity. With great power -comes great responsibility; don't put any nasty code here. To reiterate, code in -this file will be directly executed on the build slaves. -""" - - -import os -import sys - - -if 'import_path' in globals(): - sys.path.append(import_path) - - -from bench_pictures_cfg_helper import * - - -# Default tile sizes -DEFAULT_TILE_X = '256' -DEFAULT_TILE_Y = '256' - -# Default viewport size -DEFAULT_VIEWPORT_X = 1000 -DEFAULT_VIEWPORT_Y = 1000 - -# Default scale factor for scaled configs. -DEFAULT_SCALE = 1.1 - -# Configs to run on most bots -default_configs = [ - # Viewport CPU and GPU - ViewportBitmapConfig(DEFAULT_VIEWPORT_X, DEFAULT_VIEWPORT_Y), - ViewportGPUConfig(DEFAULT_VIEWPORT_X, DEFAULT_VIEWPORT_Y), - - # Scaled viewport, CPU and GPU - ViewportBitmapConfig(DEFAULT_VIEWPORT_X, DEFAULT_VIEWPORT_Y, - scale=str(DEFAULT_SCALE)), - ViewportGPUConfig(DEFAULT_VIEWPORT_X, DEFAULT_VIEWPORT_Y, - scale=str(DEFAULT_SCALE)), -] - -default_no_gpu = [cfg for cfg in default_configs if cfg['config'] != 'gpu'] - - -msaa4 = Config(config='msaa4', viewport=[str(DEFAULT_VIEWPORT_X), - str(DEFAULT_VIEWPORT_Y)]) - -msaa16 = Config(config='msaa16', viewport=[str(DEFAULT_VIEWPORT_X), - str(DEFAULT_VIEWPORT_Y)]) - -viewport_angle = Config(config='angle', viewport=[str(DEFAULT_VIEWPORT_X), - str(DEFAULT_VIEWPORT_Y)]) - -# This dictionary defines the sets of configs for all platforms. Each config is -# a dictionary of key/value pairs directly corresponding to the command-line -# flags passed to bench_pictures. -bench_pictures_cfg = { - 'angle': [viewport_angle], - 'debug': [ViewportBitmapConfig(DEFAULT_VIEWPORT_X, DEFAULT_VIEWPORT_Y)], - 'default': default_configs, - 'no_gpu': default_no_gpu, - 'nexus_s': default_no_gpu, - 'xoom': default_configs, - 'galaxy_nexus': default_configs, - 'nexus_4': default_configs + [msaa4], - 'nexus_7': default_configs, - 'nexus_10': default_configs + [msaa4], - 'razr_i': default_configs + [msaa4], - 'intel_rhb': default_no_gpu, - 'default_msaa16': default_configs + [msaa16], -} diff --git a/tools/bench_pictures_cfg_helper.py b/tools/bench_pictures_cfg_helper.py deleted file mode 100644 index c010f3b3aa..0000000000 --- a/tools/bench_pictures_cfg_helper.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - - -""" Helper functions to be used in bench_pictures.cfg. """ - - -def Config(**kwargs): - config = {} - for key in kwargs: - config[key] = kwargs[key] - return config - - -def TileArgs(tile_x, tile_y, timeIndividualTiles=True): - config = {'mode': ['tile', str(tile_x), str(tile_y)]} - if timeIndividualTiles: - config['timeIndividualTiles'] = True - return config - - -def BitmapConfig(**kwargs): - return Config(config='8888', **kwargs) - - -def GPUConfig(**kwargs): - return Config(config='gpu', **kwargs) - - -def TiledBitmapConfig(tile_x, tile_y, timeIndividualTiles=True, **kwargs): - return BitmapConfig(**dict(TileArgs(tile_x, tile_y, - timeIndividualTiles=timeIndividualTiles).items() + kwargs.items())) - - -def TiledGPUConfig(tile_x, tile_y, **kwargs): - return GPUConfig(**dict(TileArgs(tile_x, tile_y).items() + kwargs.items())) - - -def TiledConfig(tile_x, tile_y, timeIndividualTiles=True, **kwargs): - return Config(**dict(TileArgs(tile_x, tile_y, - timeIndividualTiles=timeIndividualTiles).items() + kwargs.items())) - - -def ViewportBitmapConfig(viewport_x, viewport_y, **kwargs): - return BitmapConfig(viewport=[str(viewport_x), str(viewport_y)], **kwargs) - - -def ViewportGPUConfig(viewport_x, viewport_y, **kwargs): - return GPUConfig(viewport=[str(viewport_x), str(viewport_y)], **kwargs) - - -def ViewportRTreeConfig(viewport_x, viewport_y, **kwargs): - return RTreeConfig(mode='simple', viewport=[str(viewport_x), str(viewport_y)], - **kwargs) - - -def ViewportGridConfig(viewport_x, viewport_y, **kwargs): - return GridConfig(viewport_x, viewport_y, mode='simple', - viewport=[str(viewport_x), str(viewport_y)], **kwargs) - - -def CopyTilesConfig(tile_x, tile_y, **kwargs): - return BitmapConfig(mode=['copyTile', str(tile_x), str(tile_y)], **kwargs) - - -def RecordConfig(**kwargs): - return BitmapConfig(mode='record', **kwargs) - - -def PlaybackCreationConfig(**kwargs): - return BitmapConfig(mode='playbackCreation', **kwargs) - - -def MultiThreadTileConfig(threads, tile_x, tile_y, **kwargs): - return TiledBitmapConfig(tile_x=tile_x, tile_y=tile_y, - timeIndividualTiles=False, multi=str(threads), - **kwargs) - - -def RTreeConfig(**kwargs): - return BitmapConfig(bbh='rtree', **kwargs) - - -def GridConfig(tile_x, tile_y, mode, **kwargs): - return BitmapConfig(mode=mode, bbh=['grid', str(tile_x), str(tile_y)], - **kwargs) - - -def RecordRTreeConfig(**kwargs): - return RTreeConfig(mode='record', **kwargs) - - -def PlaybackCreationRTreeConfig(**kwargs): - return RTreeConfig(mode='playbackCreation', **kwargs) - - -def TileRTreeConfig(tile_x, tile_y, **kwargs): - return RTreeConfig(**dict(TileArgs(tile_x, tile_y).items() + kwargs.items())) - - -def RecordGridConfig(tile_x, tile_y, **kwargs): - return GridConfig(tile_x=tile_x, tile_y=tile_y, mode='record', **kwargs) - - -def PlaybackCreationGridConfig(tile_x, tile_y, **kwargs): - return GridConfig(tile_x, tile_y, mode='playbackCreation') diff --git a/tools/bench_pictures_main.cpp b/tools/bench_pictures_main.cpp deleted file mode 100644 index 79cce56dca..0000000000 --- a/tools/bench_pictures_main.cpp +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "BenchLogger.h" -#include "Timer.h" -#include "CopyTilesRenderer.h" -#include "CrashHandler.h" -#include "LazyDecodeBitmap.h" -#include "PictureBenchmark.h" -#include "PictureRenderingFlags.h" -#include "PictureResultsWriter.h" -#include "SkCommandLineFlags.h" -#include "SkData.h" -#include "SkDiscardableMemoryPool.h" -#include "SkGraphics.h" -#include "SkImageDecoder.h" -#include "SkMath.h" -#include "SkOSFile.h" -#include "SkPicture.h" -#include "SkStream.h" -#include "picture_utils.h" - -BenchLogger gLogger; -PictureResultsLoggerWriter gLogWriter(&gLogger); -PictureResultsMultiWriter gWriter; - -// Flags used by this file, in alphabetical order. -DEFINE_bool(countRAM, false, "Count the RAM used for bitmap pixels in each skp file"); -DECLARE_bool(deferImageDecoding); -DEFINE_string(filter, "", - "type:flag : Enable canvas filtering to disable a paint flag, " - "use no blur or low quality blur, or use no hinting or " - "slight hinting. For all flags except AAClip, specify the " - "type of primitive to effect, or choose all. for AAClip " - "alone, the filter affects all clips independent of type. " - "Specific flags are listed above."); -DEFINE_string(logFile, "", "Destination for writing log output, in addition to stdout."); -DEFINE_bool(logPerIter, false, "Log each repeat timer instead of mean."); -DEFINE_string(jsonLog, "", "Destination for writing JSON data."); -DEFINE_bool(min, false, "Print the minimum times (instead of average)."); -DECLARE_string(readPath); -DEFINE_int32(repeat, 1, "Set the number of times to repeat each test."); -DEFINE_bool(timeIndividualTiles, false, "Report times for drawing individual tiles, rather than " - "times for drawing the whole page. Requires tiled rendering."); -DEFINE_bool(purgeDecodedTex, false, "Purge decoded and GPU-uploaded textures " - "after each iteration."); -DEFINE_string(timers, "c", "[wcgWC]*: Display wall, cpu, gpu, truncated wall or truncated cpu time" - " for each picture."); -DEFINE_bool(trackDeferredCaching, false, "Only meaningful with --deferImageDecoding and " - "SK_LAZY_CACHE_STATS set to true. Report percentage of cache hits when using " - "deferred image decoding."); - -#if GR_GPU_STATS -DEFINE_bool(gpuStats, false, "Only meaningful with gpu configurations. " - "Report some GPU call statistics."); -#endif - -DEFINE_bool(mpd, false, "If true, use MultiPictureDraw to render."); - -// Buildbot-specific parameters -DEFINE_string(builderName, "", "Name of the builder this is running on."); -DEFINE_int32(buildNumber, -1, "Build number of the build this test is running on"); -DEFINE_int32(timestamp, 0, "Timestamp of the revision of Skia being tested."); -DEFINE_string(gitHash, "", "Commit hash of the revision of Skia being run."); -DEFINE_int32(gitNumber, -1, "Git number of the revision of Skia being run."); - - -static char const * const gFilterTypes[] = { - "paint", - "point", - "line", - "bitmap", - "rect", - "oval", - "path", - "text", - "all", -}; - -static const size_t kFilterTypesCount = sizeof(gFilterTypes) / sizeof(gFilterTypes[0]); - -static char const * const gFilterFlags[] = { - "antiAlias", - "filterBitmap", - "dither", - "underlineText", - "strikeThruText", - "fakeBoldText", - "linearText", - "subpixelText", - "devKernText", - "LCDRenderText", - "embeddedBitmapText", - "autoHinting", - "verticalText", - "genA8FromLCD", - "blur", - "hinting", - "slightHinting", - "AAClip", -}; - -static const size_t kFilterFlagsCount = sizeof(gFilterFlags) / sizeof(gFilterFlags[0]); - -static SkString filtersName(sk_tools::PictureRenderer::DrawFilterFlags* drawFilters) { - int all = drawFilters[0]; - size_t tIndex; - for (tIndex = 1; tIndex < SkDrawFilter::kTypeCount; ++tIndex) { - all &= drawFilters[tIndex]; - } - SkString result; - for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) { - SkString types; - if (all & (1 << fIndex)) { - types = gFilterTypes[SkDrawFilter::kTypeCount]; - } else { - for (tIndex = 0; tIndex < SkDrawFilter::kTypeCount; ++tIndex) { - if (drawFilters[tIndex] & (1 << fIndex)) { - types += gFilterTypes[tIndex]; - } - } - } - if (!types.size()) { - continue; - } - result += "_"; - result += types; - result += "."; - result += gFilterFlags[fIndex]; - } - return result; -} - -static SkString filterTypesUsage() { - SkString result; - for (size_t index = 0; index < kFilterTypesCount; ++index) { - result += gFilterTypes[index]; - if (index < kFilterTypesCount - 1) { - result += " | "; - } - } - return result; -} - -static SkString filterFlagsUsage() { - SkString result; - size_t len = 0; - for (size_t index = 0; index < kFilterFlagsCount; ++index) { - result += gFilterFlags[index]; - if (result.size() - len >= 72) { - result += "\n\t\t"; - len = result.size(); - } - if (index < kFilterFlagsCount - 1) { - result += " | "; - } - } - return result; -} - -#if SK_LAZY_CACHE_STATS -static int32_t gTotalCacheHits; -static int32_t gTotalCacheMisses; -#endif - -static bool run_single_benchmark(const SkString& inputPath, - sk_tools::PictureBenchmark& benchmark) { - SkFILEStream inputStream; - - inputStream.setPath(inputPath.c_str()); - if (!inputStream.isValid()) { - SkString err; - err.printf("Could not open file %s\n", inputPath.c_str()); - gLogger.logError(err); - return false; - } - - SkDiscardableMemoryPool* pool = SkGetGlobalDiscardableMemoryPool(); - // Since the old picture has been deleted, all pixels should be cleared. - SkASSERT(pool->getRAMUsed() == 0); - if (FLAGS_countRAM) { - pool->setRAMBudget(SK_MaxU32); - // Set the limit to max, so all pixels will be kept - } - - SkPicture::InstallPixelRefProc proc; - if (FLAGS_deferImageDecoding) { - proc = &sk_tools::LazyDecodeBitmap; - } else { - proc = &SkImageDecoder::DecodeMemory; - } - SkAutoTUnref<SkPicture> picture(SkPicture::CreateFromStream(&inputStream, proc)); - - if (nullptr == picture.get()) { - SkString err; - err.printf("Could not read an SkPicture from %s\n", inputPath.c_str()); - gLogger.logError(err); - return false; - } - - SkString filename = SkOSPath::Basename(inputPath.c_str()); - - gWriter.bench(filename.c_str(), - SkScalarCeilToInt(picture->cullRect().width()), - SkScalarCeilToInt(picture->cullRect().height())); - - benchmark.run(picture, FLAGS_mpd); - -#if SK_LAZY_CACHE_STATS - if (FLAGS_trackDeferredCaching) { - int cacheHits = pool->getCacheHits(); - int cacheMisses = pool->getCacheMisses(); - pool->resetCacheHitsAndMisses(); - SkString hitString; - hitString.printf("Cache hit rate: %f\n", (double) cacheHits / (cacheHits + cacheMisses)); - gLogger.logProgress(hitString); - gTotalCacheHits += cacheHits; - gTotalCacheMisses += cacheMisses; - } -#endif - if (FLAGS_countRAM) { - SkString ramCount("RAM used for bitmaps: "); - size_t bytes = pool->getRAMUsed(); - if (bytes > 1024) { - size_t kb = bytes / 1024; - if (kb > 1024) { - size_t mb = kb / 1024; - ramCount.appendf("%zi MB\n", mb); - } else { - ramCount.appendf("%zi KB\n", kb); - } - } else { - ramCount.appendf("%zi bytes\n", bytes); - } - gLogger.logProgress(ramCount); - } - - return true; -} - -static void setup_benchmark(sk_tools::PictureBenchmark* benchmark) { - sk_tools::PictureRenderer::DrawFilterFlags drawFilters[SkDrawFilter::kTypeCount]; - sk_bzero(drawFilters, sizeof(drawFilters)); - - if (FLAGS_filter.count() > 0) { - const char* filters = FLAGS_filter[0]; - const char* colon = strchr(filters, ':'); - if (colon) { - int32_t type = -1; - size_t typeLen = colon - filters; - for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) { - if (typeLen == strlen(gFilterTypes[tIndex]) - && !strncmp(filters, gFilterTypes[tIndex], typeLen)) { - type = SkToS32(tIndex); - break; - } - } - if (type < 0) { - SkString err; - err.printf("Unknown type for --filter %s\n", filters); - gLogger.logError(err); - exit(-1); - } - int flag = -1; - size_t flagLen = strlen(filters) - typeLen - 1; - for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) { - if (flagLen == strlen(gFilterFlags[fIndex]) - && !strncmp(colon + 1, gFilterFlags[fIndex], flagLen)) { - flag = 1 << fIndex; - break; - } - } - if (flag < 0) { - SkString err; - err.printf("Unknown flag for --filter %s\n", filters); - gLogger.logError(err); - exit(-1); - } - for (int index = 0; index < SkDrawFilter::kTypeCount; ++index) { - if (type != SkDrawFilter::kTypeCount && index != type) { - continue; - } - drawFilters[index] = (sk_tools::PictureRenderer::DrawFilterFlags) - (drawFilters[index] | flag); - } - } else { - SkString err; - err.printf("Unknown arg for --filter %s : missing colon\n", filters); - gLogger.logError(err); - exit(-1); - } - } - - if (FLAGS_timers.count() > 0) { - size_t index = 0; - bool timerWall = false; - bool truncatedTimerWall = false; - bool timerCpu = false; - bool truncatedTimerCpu = false; - bool timerGpu = false; - while (index < strlen(FLAGS_timers[0])) { - switch (FLAGS_timers[0][index]) { - case 'w': - timerWall = true; - break; - case 'c': - timerCpu = true; - break; - case 'W': - truncatedTimerWall = true; - break; - case 'C': - truncatedTimerCpu = true; - break; - case 'g': - timerGpu = true; - break; - default: - SkDebugf("mystery character\n"); - break; - } - index++; - } - benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu, truncatedTimerCpu, - timerGpu); - } - - SkString errorString; - SkAutoTUnref<sk_tools::PictureRenderer> renderer(parseRenderer(errorString, - kBench_PictureTool)); - - if (errorString.size() > 0) { - gLogger.logError(errorString); - } - - if (nullptr == renderer.get()) { - exit(-1); - } - - if (FLAGS_timeIndividualTiles) { - sk_tools::TiledPictureRenderer* tiledRenderer = renderer->getTiledRenderer(); - if (nullptr == tiledRenderer) { - gLogger.logError("--timeIndividualTiles requires tiled rendering.\n"); - exit(-1); - } - if (!tiledRenderer->supportsTimingIndividualTiles()) { - gLogger.logError("This renderer does not support --timeIndividualTiles.\n"); - exit(-1); - } - benchmark->setTimeIndividualTiles(true); - } - - benchmark->setPurgeDecodedTex(FLAGS_purgeDecodedTex); - - if (FLAGS_readPath.count() < 1) { - gLogger.logError(".skp files or directories are required.\n"); - exit(-1); - } - - renderer->setDrawFilters(drawFilters, filtersName(drawFilters)); - if (FLAGS_logPerIter) { - benchmark->setTimerResultType(TimerData::kPerIter_Result); - } else if (FLAGS_min) { - benchmark->setTimerResultType(TimerData::kMin_Result); - } else { - benchmark->setTimerResultType(TimerData::kAvg_Result); - } - benchmark->setRenderer(renderer); - benchmark->setRepeats(FLAGS_repeat); - benchmark->setWriter(&gWriter); -} - -static int process_input(const char* input, - sk_tools::PictureBenchmark& benchmark) { - SkString inputAsSkString(input); - SkOSFile::Iter iter(input, "skp"); - SkString inputFilename; - int failures = 0; - if (iter.next(&inputFilename)) { - do { - SkString inputPath = SkOSPath::Join(input, inputFilename.c_str()); - if (!run_single_benchmark(inputPath, benchmark)) { - ++failures; - } - } while(iter.next(&inputFilename)); - } else if (SkStrEndsWith(input, ".skp")) { - if (!run_single_benchmark(inputAsSkString, benchmark)) { - ++failures; - } - } else { - SkString warning; - warning.printf("Warning: skipping %s\n", input); - gLogger.logError(warning); - } - return failures; -} - -int tool_main(int argc, char** argv); -int tool_main(int argc, char** argv) { - SetupCrashHandler(); - SkString usage; - usage.printf("Time drawing .skp files.\n" - "\tPossible arguments for --filter: [%s]\n\t\t[%s]", - filterTypesUsage().c_str(), filterFlagsUsage().c_str()); - SkCommandLineFlags::SetUsage(usage.c_str()); - SkCommandLineFlags::Parse(argc, argv); - - if (FLAGS_repeat < 1) { - SkString error; - error.printf("--repeats must be >= 1. Was %i\n", FLAGS_repeat); - gLogger.logError(error); - exit(-1); - } - - if (FLAGS_logFile.count() == 1) { - if (!gLogger.SetLogFile(FLAGS_logFile[0])) { - SkString str; - str.printf("Could not open %s for writing.\n", FLAGS_logFile[0]); - gLogger.logError(str); - // TODO(borenet): We're disabling this for now, due to - // write-protected Android devices. The very short-term - // solution is to ignore the fact that we have no log file. - //exit(-1); - } - } - - SkAutoTDelete<PictureJSONResultsWriter> jsonWriter; - if (FLAGS_jsonLog.count() == 1) { - SkASSERT(FLAGS_builderName.count() == 1 && FLAGS_gitHash.count() == 1); - jsonWriter.reset(new PictureJSONResultsWriter(FLAGS_jsonLog[0], FLAGS_builderName[0], - FLAGS_buildNumber, FLAGS_timestamp, - FLAGS_gitHash[0], FLAGS_gitNumber)); - gWriter.add(jsonWriter.get()); - } - - gWriter.add(&gLogWriter); - - - SkAutoGraphics ag; - - sk_tools::PictureBenchmark benchmark; - - setup_benchmark(&benchmark); - - int failures = 0; - for (int i = 0; i < FLAGS_readPath.count(); ++i) { - failures += process_input(FLAGS_readPath[i], benchmark); - } - - if (failures != 0) { - SkString err; - err.printf("Failed to run %i benchmarks.\n", failures); - gLogger.logError(err); - return 1; - } -#if SK_LAZY_CACHE_STATS - if (FLAGS_trackDeferredCaching) { - SkDebugf("Total cache hit rate: %f\n", - (double) gTotalCacheHits / (gTotalCacheHits + gTotalCacheMisses)); - } -#endif - -#if GR_GPU_STATS && SK_SUPPORT_GPU - if (FLAGS_gpuStats && benchmark.renderer()->isUsingGpuDevice()) { - benchmark.renderer()->getGrContext()->printGpuStats(); - } -#endif - - gWriter.end(); - return 0; -} - -#if !defined SK_BUILD_FOR_IOS -int main(int argc, char * const argv[]) { - return tool_main(argc, (char**) argv); -} -#endif diff --git a/tools/chromium/chrome_changes b/tools/chromium/chrome_changes deleted file mode 100644 index 18f67e7520..0000000000 --- a/tools/chromium/chrome_changes +++ /dev/null @@ -1,7 +0,0 @@ -# This file contains references to Chrome CLs which are associated with Skia -# changes. If your Skia change requires a change in Chrome, add a line to this -# file which contains the codereview issue(s) for the Chrome change, eg: -# https://codereview.chromium.org/249493003/ -# In the future, these changes will be automatically applied and committed as -# part of the DEPS roll which contains the Skia change. -https://codereview.chromium.org/265513005/ diff --git a/tools/dump_record.cpp b/tools/dump_record.cpp deleted file mode 100644 index 69cdffff31..0000000000 --- a/tools/dump_record.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <stdio.h> - -#include "SkCommandLineFlags.h" -#include "SkGraphics.h" -#include "SkPicture.h" -#include "SkRecordOpts.h" -#include "SkRecorder.h" -#include "SkStream.h" - -#include "DumpRecord.h" -#include "LazyDecodeBitmap.h" - -#include <stdlib.h> - -DEFINE_string2(skps, r, "", ".SKPs to dump."); -DEFINE_string(match, "", "The usual filters on file names to dump."); -DEFINE_bool2(optimize, O, false, "Run SkRecordOptimize before dumping."); -DEFINE_int32(tile, 1000000000, "Simulated tile size."); -DEFINE_bool(timeWithCommand, false, "If true, print time next to command, else in first column."); - -static void dump(const char* name, int w, int h, const SkRecord& record) { - SkBitmap bitmap; - bitmap.allocN32Pixels(w, h); - SkCanvas canvas(bitmap); - canvas.clipRect(SkRect::MakeWH(SkIntToScalar(FLAGS_tile), - SkIntToScalar(FLAGS_tile))); - - printf("%s %s\n", FLAGS_optimize ? "optimized" : "not-optimized", name); - - DumpRecord(record, &canvas, FLAGS_timeWithCommand); -} - - -int tool_main(int argc, char** argv); -int tool_main(int argc, char** argv) { - SkCommandLineFlags::Parse(argc, argv); - SkAutoGraphics ag; - - for (int i = 0; i < FLAGS_skps.count(); i++) { - if (SkCommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) { - continue; - } - - SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(FLAGS_skps[i])); - if (!stream) { - SkDebugf("Could not read %s.\n", FLAGS_skps[i]); - exit(1); - } - SkAutoTUnref<SkPicture> src( - SkPicture::CreateFromStream(stream, sk_tools::LazyDecodeBitmap)); - if (!src) { - SkDebugf("Could not read %s as an SkPicture.\n", FLAGS_skps[i]); - exit(1); - } - const int w = SkScalarCeilToInt(src->cullRect().width()); - const int h = SkScalarCeilToInt(src->cullRect().height()); - - SkRecord record; - SkRecorder canvas(&record, w, h); - src->playback(&canvas); - - if (FLAGS_optimize) { - SkRecordOptimize(&record); - } - - dump(FLAGS_skps[i], w, h, record); - } - - return 0; -} - -#if !defined SK_BUILD_FOR_IOS -int main(int argc, char * const argv[]) { - return tool_main(argc, (char**) argv); -} -#endif diff --git a/tools/flatten.cpp b/tools/flatten.cpp deleted file mode 100644 index 8ba20929fb..0000000000 --- a/tools/flatten.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2015 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkData.h" -#include "SkForceLinking.h" -#include "SkImageGenerator.h" -#include "SkPicture.h" -#include "SkPictureRecorder.h" -#include "SkStream.h" - -#include <stdlib.h> -#include <stdio.h> - -__SK_FORCE_IMAGE_DECODER_LINKING; - -#define ASSERTF(cond, fmt, ...) if (!(cond)) { fprintf(stderr, fmt"\n", __VA_ARGS__); exit(1); } - -static bool lazy_decode_bitmap(const void* src, size_t size, SkBitmap* dst) { - SkAutoTUnref<SkData> encoded(SkData::NewWithCopy(src, size)); - return encoded && SkDEPRECATED_InstallDiscardablePixelRef(encoded, dst); -} - -int main(int argc, char** argv) { - ASSERTF(argc == 3, "usage: %s nested.skp flat.skp", argv[0]); - const char *nestedPath = argv[1], - *flatPath = argv[2]; - - // Read nested.skp. - SkFILEStream stream(nestedPath); - ASSERTF(stream.isValid(), "Couldn't read %s.", nestedPath); - SkAutoTUnref<const SkPicture> nested(SkPicture::CreateFromStream(&stream, &lazy_decode_bitmap)); - ASSERTF(nested, "Couldn't parse %s as a picture.", nestedPath); - - // Play it back into a new picture using kPlaybackDrawPicture_RecordFlag. - SkPictureRecorder recorder; - uint32_t flags = SkPictureRecorder::kPlaybackDrawPicture_RecordFlag; - nested->playback(recorder.beginRecording(nested->cullRect(), nullptr, flags)); - SkAutoTUnref<const SkPicture> flat(recorder.endRecordingAsPicture()); - - // Write out that flat.skp - SkFILEWStream wstream(flatPath); - ASSERTF(wstream.isValid(), "Could not open %s.", flatPath); - flat->serialize(&wstream); - wstream.flush(); - - return 0; -} diff --git a/tools/image_expectations.cpp b/tools/image_expectations.cpp deleted file mode 100644 index cb0c03afc6..0000000000 --- a/tools/image_expectations.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkBitmap.h" -#include "SkBitmapHasher.h" -#include "SkData.h" -#include "SkJSONCPP.h" -#include "SkOSFile.h" -#include "SkStream.h" -#include "SkTypes.h" - -#include "image_expectations.h" - -/* - * TODO(epoger): Make constant strings consistent instead of mixing hypenated and camel-caps. - * - * TODO(epoger): Similar constants are already maintained in 2 other places: - * gm/gm_json.py and gm/gm_expectations.cpp. We shouldn't add yet a third place. - * Figure out a way to share the definitions instead. - * - * Note that, as of https://codereview.chromium.org/226293002 , the JSON - * schema used here has started to differ from the one in gm_expectations.cpp . - * TODO(epoger): Consider getting GM and render_pictures to use the same JSON - * output module. - */ -const static char kJsonKey_ActualResults[] = "actual-results"; -const static char kJsonKey_Descriptions[] = "descriptions"; -const static char kJsonKey_ExpectedResults[] = "expected-results"; -const static char kJsonKey_ImageBaseGSUrl[] = "image-base-gs-url"; -const static char kJsonKey_Header[] = "header"; -const static char kJsonKey_Header_Type[] = "type"; -const static char kJsonKey_Header_Revision[] = "revision"; -const static char kJsonKey_Image_ChecksumAlgorithm[] = "checksumAlgorithm"; -const static char kJsonKey_Image_ChecksumValue[] = "checksumValue"; -const static char kJsonKey_Image_ComparisonResult[] = "comparisonResult"; -const static char kJsonKey_Image_Filepath[] = "filepath"; -const static char kJsonKey_Image_IgnoreFailure[] = "ignoreFailure"; -const static char kJsonKey_Source_TiledImages[] = "tiled-images"; -const static char kJsonKey_Source_WholeImage[] = "whole-image"; -// Values (not keys) that are written out by this JSON generator -const static char kJsonValue_Header_Type[] = "ChecksummedImages"; -const static int kJsonValue_Header_Revision = 1; -const static char kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5[] = "bitmap-64bitMD5"; -const static char kJsonValue_Image_ComparisonResult_Failed[] = "failed"; -const static char kJsonValue_Image_ComparisonResult_FailureIgnored[] = "failure-ignored"; -const static char kJsonValue_Image_ComparisonResult_NoComparison[] = "no-comparison"; -const static char kJsonValue_Image_ComparisonResult_Succeeded[] = "succeeded"; - -namespace sk_tools { - - // ImageDigest class... - - ImageDigest::ImageDigest(const SkBitmap &bitmap) : - fBitmap(bitmap), fHashValue(0), fComputedHashValue(false) {} - - ImageDigest::ImageDigest(const SkString &hashType, uint64_t hashValue) : - fBitmap(), fHashValue(hashValue), fComputedHashValue(true) { - if (!hashType.equals(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5)) { - SkDebugf("unsupported hashType '%s'\n", hashType.c_str()); - SkFAIL("unsupported hashType (see above)"); - } - } - - bool ImageDigest::equals(ImageDigest &other) { - // TODO(epoger): The current implementation assumes that this - // and other always have hashType kJsonKey_Hashtype_Bitmap_64bitMD5 - return (this->getHashValue() == other.getHashValue()); - } - - SkString ImageDigest::getHashType() { - // TODO(epoger): The current implementation assumes that the - // result digest is always of type kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5 . - return SkString(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5); - } - - uint64_t ImageDigest::getHashValue() { - if (!this->fComputedHashValue) { - if (!SkBitmapHasher::ComputeDigest(this->fBitmap, &this->fHashValue)) { - SkFAIL("unable to compute image digest"); - } - this->fComputedHashValue = true; - } - return this->fHashValue; - } - - // BitmapAndDigest class... - - BitmapAndDigest::BitmapAndDigest(const SkBitmap &bitmap) : - fBitmap(bitmap), fImageDigest(bitmap) {} - - const SkBitmap *BitmapAndDigest::getBitmapPtr() const {return &fBitmap;} - - ImageDigest *BitmapAndDigest::getImageDigestPtr() {return &fImageDigest;} - - // Expectation class... - - // For when we need a valid ImageDigest, but we don't care what it is. - static const ImageDigest kDummyImageDigest( - SkString(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5), 0); - - Expectation::Expectation(bool ignoreFailure) : - fIsEmpty(true), fIgnoreFailure(ignoreFailure), fImageDigest(kDummyImageDigest) {} - - Expectation::Expectation(const SkString &hashType, uint64_t hashValue, bool ignoreFailure) : - fIsEmpty(false), fIgnoreFailure(ignoreFailure), fImageDigest(hashType, hashValue) {} - - Expectation::Expectation(const SkBitmap& bitmap, bool ignoreFailure) : - fIsEmpty(false), fIgnoreFailure(ignoreFailure), fImageDigest(bitmap) {} - - bool Expectation::ignoreFailure() const { return this->fIgnoreFailure; } - - bool Expectation::empty() const { return this->fIsEmpty; } - - bool Expectation::matches(ImageDigest &imageDigest) { - return !(this->fIsEmpty) && (this->fImageDigest.equals(imageDigest)); - } - - // ImageResultsAndExpectations class... - - bool ImageResultsAndExpectations::readExpectationsFile(const char *jsonPath) { - if (nullptr == jsonPath) { - SkDebugf("JSON expectations filename not specified\n"); - return false; - } - SkFILE* filePtr = sk_fopen(jsonPath, kRead_SkFILE_Flag); - if (nullptr == filePtr) { - SkDebugf("JSON expectations file '%s' does not exist\n", jsonPath); - return false; - } - size_t size = sk_fgetsize(filePtr); - if (0 == size) { - SkDebugf("JSON expectations file '%s' is empty, so no expectations\n", jsonPath); - sk_fclose(filePtr); - fExpectedResults.clear(); - return true; - } - bool parsedJson = Parse(filePtr, &fExpectedJsonRoot); - sk_fclose(filePtr); - if (!parsedJson) { - SkDebugf("Failed to parse JSON expectations file '%s'\n", jsonPath); - return false; - } - Json::Value header = fExpectedJsonRoot[kJsonKey_Header]; - Json::Value headerType = header[kJsonKey_Header_Type]; - Json::Value headerRevision = header[kJsonKey_Header_Revision]; - if (strcmp(headerType.asCString(), kJsonValue_Header_Type)) { - SkDebugf("JSON expectations file '%s': expected headerType '%s', found '%s'\n", - jsonPath, kJsonValue_Header_Type, headerType.asCString()); - return false; - } - if (headerRevision.asInt() != kJsonValue_Header_Revision) { - SkDebugf("JSON expectations file '%s': expected headerRevision %d, found %d\n", - jsonPath, kJsonValue_Header_Revision, headerRevision.asInt()); - return false; - } - fExpectedResults = fExpectedJsonRoot[kJsonKey_ExpectedResults]; - return true; - } - - void ImageResultsAndExpectations::add(const char *sourceName, const char *fileName, - ImageDigest &digest, const int *tileNumber) { - // Get expectation, if any. - Expectation expectation = this->getExpectation(sourceName, tileNumber); - - // Fill in info about the actual result. - Json::Value actualChecksumAlgorithm = digest.getHashType().c_str(); - Json::Value actualChecksumValue = Json::UInt64(digest.getHashValue()); - Json::Value actualImage; - actualImage[kJsonKey_Image_ChecksumAlgorithm] = actualChecksumAlgorithm; - actualImage[kJsonKey_Image_ChecksumValue] = actualChecksumValue; - actualImage[kJsonKey_Image_Filepath] = fileName; - - // Compare against expectedImage to fill in comparisonResult. - Json::Value comparisonResult; - if (expectation.empty()) { - comparisonResult = kJsonValue_Image_ComparisonResult_NoComparison; - } else if (expectation.matches(digest)) { - comparisonResult = kJsonValue_Image_ComparisonResult_Succeeded; - } else if (expectation.ignoreFailure()) { - comparisonResult = kJsonValue_Image_ComparisonResult_FailureIgnored; - } else { - comparisonResult = kJsonValue_Image_ComparisonResult_Failed; - } - actualImage[kJsonKey_Image_ComparisonResult] = comparisonResult; - - // Add this actual result to our collection. - if (nullptr == tileNumber) { - fActualResults[sourceName][kJsonKey_Source_WholeImage] = actualImage; - } else { - fActualResults[sourceName][kJsonKey_Source_TiledImages][*tileNumber] = actualImage; - } - } - - void ImageResultsAndExpectations::addDescription(const char *key, const char *value) { - fDescriptions[key] = value; - } - - void ImageResultsAndExpectations::setImageBaseGSUrl(const char *imageBaseGSUrl) { - fImageBaseGSUrl = imageBaseGSUrl; - } - - Expectation ImageResultsAndExpectations::getExpectation(const char *sourceName, - const int *tileNumber) { - if (fExpectedResults.isNull()) { - return Expectation(); - } - - Json::Value expectedImage; - if (nullptr == tileNumber) { - expectedImage = fExpectedResults[sourceName][kJsonKey_Source_WholeImage]; - } else { - expectedImage = fExpectedResults[sourceName][kJsonKey_Source_TiledImages][*tileNumber]; - } - if (expectedImage.isNull()) { - return Expectation(); - } - - bool ignoreFailure = (expectedImage[kJsonKey_Image_IgnoreFailure] == true); - return Expectation(SkString(expectedImage[kJsonKey_Image_ChecksumAlgorithm].asCString()), - expectedImage[kJsonKey_Image_ChecksumValue].asUInt64(), - ignoreFailure); - } - - void ImageResultsAndExpectations::writeToFile(const char *filename) const { - Json::Value header; - header[kJsonKey_Header_Type] = kJsonValue_Header_Type; - header[kJsonKey_Header_Revision] = kJsonValue_Header_Revision; - Json::Value root; - root[kJsonKey_ActualResults] = fActualResults; - root[kJsonKey_Descriptions] = fDescriptions; - root[kJsonKey_Header] = header; - root[kJsonKey_ImageBaseGSUrl] = fImageBaseGSUrl; - std::string jsonStdString = root.toStyledString(); - SkFILEWStream stream(filename); - stream.write(jsonStdString.c_str(), jsonStdString.length()); - } - - /*static*/ bool ImageResultsAndExpectations::Parse(SkFILE *filePtr, - Json::Value *jsonRoot) { - SkAutoDataUnref dataRef(SkData::NewFromFILE(filePtr)); - if (nullptr == dataRef.get()) { - return false; - } - - const char *bytes = reinterpret_cast<const char *>(dataRef.get()->data()); - size_t size = dataRef.get()->size(); - Json::Reader reader; - if (!reader.parse(bytes, bytes+size, *jsonRoot)) { - return false; - } - - return true; - } - -} // namespace sk_tools diff --git a/tools/image_expectations.h b/tools/image_expectations.h deleted file mode 100644 index a72d7a2c46..0000000000 --- a/tools/image_expectations.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef image_expectations_DEFINED -#define image_expectations_DEFINED - -#include "SkBitmap.h" -#include "SkJSONCPP.h" -#include "SkOSFile.h" - -namespace sk_tools { - - /** - * The digest of an image (either an image we have generated locally, or an image expectation). - * - * Currently, this is always a uint64_t hash digest of an SkBitmap. - */ - class ImageDigest { - public: - /** - * Create an ImageDigest of a bitmap. - * - * Computes the hash of the bitmap lazily, since that is an expensive operation. - * - * @param bitmap image to get the digest of - */ - explicit ImageDigest(const SkBitmap &bitmap); - - /** - * Create an ImageDigest using a hashType/hashValue pair. - * - * @param hashType the algorithm used to generate the hash; for now, only - * kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5 is allowed. - * @param hashValue the value generated by the hash algorithm for a particular image. - */ - explicit ImageDigest(const SkString &hashType, uint64_t hashValue); - - /** - * Returns true iff this and other ImageDigest represent identical images. - */ - bool equals(ImageDigest &other); - - /** - * Returns the hash digest type as an SkString. - * - * For now, this always returns kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5 . - */ - SkString getHashType(); - - /** - * Returns the hash digest value as a uint64_t. - * - * Since the hash is computed lazily, this may take some time, and it may modify - * some fields on this object. - */ - uint64_t getHashValue(); - - private: - const SkBitmap fBitmap; - uint64_t fHashValue; - bool fComputedHashValue; - }; - - /** - * Container that holds a reference to an SkBitmap and its ImageDigest. - */ - class BitmapAndDigest { - public: - explicit BitmapAndDigest(const SkBitmap &bitmap); - - const SkBitmap *getBitmapPtr() const; - - /** - * Returns a pointer to the ImageDigest. - * - * Since the hash is computed lazily within the ImageDigest object, we cannot mandate - * that it be held const. - */ - ImageDigest *getImageDigestPtr(); - private: - const SkBitmap fBitmap; - ImageDigest fImageDigest; - }; - - /** - * Expected test result: expected image (if any), and whether we want to ignore failures on - * this test or not. - * - * This is just an ImageDigest (or lack thereof, if there is no expectation) and a boolean - * telling us whether to ignore failures. - */ - class Expectation { - public: - /** - * No expectation at all. - */ - explicit Expectation(bool ignoreFailure=kDefaultIgnoreFailure); - - /** - * Expect an image, passed as hashType/hashValue. - */ - explicit Expectation(const SkString &hashType, uint64_t hashValue, - bool ignoreFailure=kDefaultIgnoreFailure); - - /** - * Expect an image, passed as a bitmap. - */ - explicit Expectation(const SkBitmap& bitmap, - bool ignoreFailure=kDefaultIgnoreFailure); - - /** - * Returns true iff we want to ignore failed expectations. - */ - bool ignoreFailure() const; - - /** - * Returns true iff there are no allowed results. - */ - bool empty() const; - - /** - * Returns true iff we are expecting a particular image, and imageDigest matches it. - * - * If empty() returns true, this will return false. - * - * If this expectation DOES contain an image, and imageDigest doesn't match it, - * this method will return false regardless of what ignoreFailure() would return. - * (The caller can check that separately.) - */ - bool matches(ImageDigest &imageDigest); - - private: - static const bool kDefaultIgnoreFailure = false; - - const bool fIsEmpty; - const bool fIgnoreFailure; - ImageDigest fImageDigest; // cannot be const, because it computes its hash lazily - }; - - /** - * Collects ImageDigests of actually rendered images, perhaps comparing to expectations. - */ - class ImageResultsAndExpectations { - public: - /** - * Adds expectations from a JSON file, returning true if successful. - * - * If the file exists but is empty, it succeeds, and there will be no expectations. - * If the file does not exist, this will fail. - * - * Reasoning: - * Generating expectations the first time can be a tricky chicken-and-egg - * proposition. "I need actual results to turn into expectations... but the only - * way to get actual results is to run the tool, and the tool won't run without - * expectations!" - * We could make the tool run even if there is no expectations file at all, but it's - * better for the tool to fail if the expectations file is not found--that will tell us - * quickly if files are not being copied around as they should be. - * Creating an empty file is an easy way to break the chicken-and-egg cycle and generate - * the first real expectations. - */ - bool readExpectationsFile(const char *jsonPath); - - /** - * Adds this image to the summary of results. - * - * @param sourceName name of the source file that generated this result - * @param fileName relative path to the image output file on local disk - * @param digest description of the image's contents - * @param tileNumber if not nullptr, pointer to tile number - */ - void add(const char *sourceName, const char *fileName, ImageDigest &digest, - const int *tileNumber=nullptr); - - /** - * Adds a key/value pair to the descriptions dict within the summary of results. - * - * @param key key within the descriptions dict - * @param value value to associate with that key - */ - void addDescription(const char *key, const char *value); - - /** - * Adds the image base Google Storage URL to the summary of results. - * - * @param imageBaseGSUrl the image base Google Storage URL - */ - void setImageBaseGSUrl(const char *imageBaseGSUrl); - - /** - * Returns the Expectation for this test. - * - * @param sourceName name of the source file that generated this result - * @param tileNumber if not nullptr, pointer to tile number - * - * TODO(stephana): To make this work for GMs, we will need to add parameters for - * config, and maybe renderMode/builder? - */ - Expectation getExpectation(const char *sourceName, const int *tileNumber=nullptr); - - /** - * Writes the summary (as constructed so far) to a file. - * - * @param filename path to write the summary to - */ - void writeToFile(const char *filename) const; - - private: - - /** - * Read the file contents from filePtr and parse them into jsonRoot. - * - * It is up to the caller to close filePtr after this is done. - * - * Returns true if successful. - */ - static bool Parse(SkFILE* filePtr, Json::Value *jsonRoot); - - Json::Value fActualResults; - Json::Value fDescriptions; - Json::Value fExpectedJsonRoot; - Json::Value fExpectedResults; - Json::Value fImageBaseGSUrl; - }; - -} // namespace sk_tools - -#endif // image_expectations_DEFINED diff --git a/tools/render_pictures_main.cpp b/tools/render_pictures_main.cpp deleted file mode 100644 index 401c205d67..0000000000 --- a/tools/render_pictures_main.cpp +++ /dev/null @@ -1,511 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "LazyDecodeBitmap.h" -#include "CopyTilesRenderer.h" -#include "SkBitmap.h" -#include "SkDevice.h" -#include "SkCommandLineFlags.h" -#include "SkGraphics.h" -#include "SkImageDecoder.h" -#include "SkImageEncoder.h" -#include "SkMath.h" -#include "SkOSFile.h" -#include "SkPicture.h" -#include "SkPictureRecorder.h" -#include "SkStream.h" -#include "SkString.h" - -#include "image_expectations.h" -#include "PictureRenderer.h" -#include "PictureRenderingFlags.h" -#include "picture_utils.h" - -#include <stdlib.h> - -// Flags used by this file, alphabetically: -DEFINE_bool(bench_record, false, "If true, drop into an infinite loop of recording the picture."); -DECLARE_bool(deferImageDecoding); -DEFINE_string(descriptions, "", "one or more key=value pairs to add to the descriptions section " - "of the JSON summary."); -DEFINE_string(imageBaseGSUrl, "", "The Google Storage image base URL the images are stored in."); -DEFINE_int32(maxComponentDiff, 256, "Maximum diff on a component, 0 - 256. Components that differ " - "by more than this amount are considered errors, though all diffs are reported. " - "Requires --validate."); -DEFINE_string(mismatchPath, "", "Write images for tests that failed due to " - "pixel mismatches into this directory."); -#if GR_GPU_STATS -DEFINE_bool(gpuStats, false, "Only meaningful with gpu configurations. " - "Report some GPU call statistics."); -#endif -DEFINE_bool(mpd, false, "If true, use MultiPictureDraw for rendering."); -DEFINE_string(readJsonSummaryPath, "", "JSON file to read image expectations from."); -DECLARE_string(readPath); -DEFINE_bool(writeChecksumBasedFilenames, false, - "When writing out images, use checksum-based filenames."); -DEFINE_bool(writeEncodedImages, false, "Any time the skp contains an encoded image, write it to a " - "file rather than decoding it. Requires writePath to be set. Skips drawing the full " - "skp to a file. Not compatible with deferImageDecoding."); -DEFINE_string(writeJsonSummaryPath, "", "File to write a JSON summary of image results to."); -DEFINE_string2(writePath, w, "", "Directory to write the rendered images into."); -DEFINE_bool(writeWholeImage, false, "In tile mode, write the entire rendered image to a " - "file, instead of an image for each tile."); -DEFINE_bool(validate, false, "Verify that the rendered image contains the same pixels as " - "the picture rendered in simple mode. When used in conjunction with --bbh, results " - "are validated against the picture rendered in the same mode, but without the bbh."); - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * Table for translating from format of data to a suffix. - */ -struct Format { - SkImageDecoder::Format fFormat; - const char* fSuffix; -}; -static const Format gFormats[] = { - { SkImageDecoder::kBMP_Format, ".bmp" }, - { SkImageDecoder::kGIF_Format, ".gif" }, - { SkImageDecoder::kICO_Format, ".ico" }, - { SkImageDecoder::kJPEG_Format, ".jpg" }, - { SkImageDecoder::kPNG_Format, ".png" }, - { SkImageDecoder::kWBMP_Format, ".wbmp" }, - { SkImageDecoder::kWEBP_Format, ".webp" }, - { SkImageDecoder::kUnknown_Format, "" }, -}; - -/** - * Get an appropriate suffix for an image format. - */ -static const char* get_suffix_from_format(SkImageDecoder::Format format) { - for (size_t i = 0; i < SK_ARRAY_COUNT(gFormats); i++) { - if (gFormats[i].fFormat == format) { - return gFormats[i].fSuffix; - } - } - return ""; -} - -/** - * Base name for an image file created from the encoded data in an skp. - */ -static SkString gInputFileName; - -/** - * Number to be appended to the image file name so that it is unique. - */ -static uint32_t gImageNo; - -/** - * Set up the name for writing encoded data to a file. - * Sets gInputFileName to name, minus any extension ".*" - * Sets gImageNo to 0, so images from file "X.skp" will - * look like "X_<gImageNo>.<suffix>", beginning with 0 - * for each new skp. - */ -static void reset_image_file_base_name(const SkString& name) { - gImageNo = 0; - // Remove ".skp" - const char* cName = name.c_str(); - const char* dot = strrchr(cName, '.'); - if (dot != nullptr) { - gInputFileName.set(cName, dot - cName); - } else { - gInputFileName.set(name); - } -} - -/** - * Write the raw encoded bitmap data to a file. - */ -static bool write_image_to_file(const void* buffer, size_t size, SkBitmap* bitmap) { - SkASSERT(!FLAGS_writePath.isEmpty()); - SkMemoryStream memStream(buffer, size); - SkString outPath; - SkImageDecoder::Format format = SkImageDecoder::GetStreamFormat(&memStream); - SkString name = SkStringPrintf("%s_%d%s", gInputFileName.c_str(), gImageNo++, - get_suffix_from_format(format)); - SkString dir(FLAGS_writePath[0]); - outPath = SkOSPath::Join(dir.c_str(), name.c_str()); - SkFILEWStream fileStream(outPath.c_str()); - if (!(fileStream.isValid() && fileStream.write(buffer, size))) { - SkDebugf("Failed to write encoded data to \"%s\"\n", outPath.c_str()); - } - // Put in a dummy bitmap. - return SkImageDecoder::DecodeStream(&memStream, bitmap, kUnknown_SkColorType, - SkImageDecoder::kDecodeBounds_Mode); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * Called only by render_picture(). - */ -static bool render_picture_internal(const SkString& inputPath, const SkString* writePath, - const SkString* mismatchPath, - sk_tools::PictureRenderer& renderer, - SkBitmap** out) { - SkString inputFilename = SkOSPath::Basename(inputPath.c_str()); - SkString writePathString; - if (writePath && writePath->size() > 0 && !FLAGS_writeEncodedImages) { - writePathString.set(*writePath); - } - SkString mismatchPathString; - if (mismatchPath && mismatchPath->size() > 0) { - mismatchPathString.set(*mismatchPath); - } - - SkFILEStream inputStream; - inputStream.setPath(inputPath.c_str()); - if (!inputStream.isValid()) { - SkDebugf("Could not open file %s\n", inputPath.c_str()); - return false; - } - - SkPicture::InstallPixelRefProc proc; - if (FLAGS_deferImageDecoding) { - proc = &sk_tools::LazyDecodeBitmap; - } else if (FLAGS_writeEncodedImages) { - SkASSERT(!FLAGS_writePath.isEmpty()); - reset_image_file_base_name(inputFilename); - proc = &write_image_to_file; - } else { - proc = &SkImageDecoder::DecodeMemory; - } - - SkDebugf("deserializing... %s\n", inputPath.c_str()); - - SkAutoTUnref<SkPicture> picture(SkPicture::CreateFromStream(&inputStream, proc)); - - if (nullptr == picture) { - SkDebugf("Could not read an SkPicture from %s\n", inputPath.c_str()); - return false; - } - - while (FLAGS_bench_record) { - SkPictureRecorder recorder; - picture->playback(recorder.beginRecording(picture->cullRect().width(), - picture->cullRect().height(), - nullptr, 0)); - SkAutoTUnref<SkPicture> other(recorder.endRecording()); - } - - SkDebugf("drawing... [%f %f %f %f] %s\n", - picture->cullRect().fLeft, picture->cullRect().fTop, - picture->cullRect().fRight, picture->cullRect().fBottom, - inputPath.c_str()); - - renderer.init(picture, &writePathString, &mismatchPathString, &inputFilename, - FLAGS_writeChecksumBasedFilenames, FLAGS_mpd); - - renderer.setup(); - renderer.enableWrites(); - - bool success = renderer.render(out); - if (!success) { - SkDebugf("Failed to render %s\n", inputFilename.c_str()); - } - - renderer.end(); - - return success; -} - -static inline int getByte(uint32_t value, int index) { - SkASSERT(0 <= index && index < 4); - return (value >> (index * 8)) & 0xFF; -} - -static int MaxByteDiff(uint32_t v1, uint32_t v2) { - return SkMax32(SkMax32(SkTAbs(getByte(v1, 0) - getByte(v2, 0)), SkTAbs(getByte(v1, 1) - getByte(v2, 1))), - SkMax32(SkTAbs(getByte(v1, 2) - getByte(v2, 2)), SkTAbs(getByte(v1, 3) - getByte(v2, 3)))); -} - -class AutoRestoreBbhType { -public: - AutoRestoreBbhType() { - fRenderer = nullptr; - fSavedBbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType; - } - - void set(sk_tools::PictureRenderer* renderer, - sk_tools::PictureRenderer::BBoxHierarchyType bbhType) { - fRenderer = renderer; - fSavedBbhType = renderer->getBBoxHierarchyType(); - renderer->setBBoxHierarchyType(bbhType); - } - - ~AutoRestoreBbhType() { - if (fRenderer) { - fRenderer->setBBoxHierarchyType(fSavedBbhType); - } - } - -private: - sk_tools::PictureRenderer* fRenderer; - sk_tools::PictureRenderer::BBoxHierarchyType fSavedBbhType; -}; - -/** - * Render the SKP file(s) within inputPath. - * - * @param inputPath path to an individual SKP file, or a directory of SKP files - * @param writePath if not nullptr, write all image(s) generated into this directory - * @param mismatchPath if not nullptr, write any image(s) not matching expectations into this directory - * @param renderer PictureRenderer to use to render the SKPs - * @param jsonSummaryPtr if not nullptr, add the image(s) generated to this summary - */ -static bool render_picture(const SkString& inputPath, const SkString* writePath, - const SkString* mismatchPath, sk_tools::PictureRenderer& renderer, - sk_tools::ImageResultsAndExpectations *jsonSummaryPtr) { - int diffs[256] = {0}; - SkBitmap* bitmap = nullptr; - renderer.setJsonSummaryPtr(jsonSummaryPtr); - bool success = render_picture_internal(inputPath, - FLAGS_writeWholeImage ? nullptr : writePath, - FLAGS_writeWholeImage ? nullptr : mismatchPath, - renderer, - FLAGS_validate || FLAGS_writeWholeImage ? &bitmap : nullptr); - - if (!success || ((FLAGS_validate || FLAGS_writeWholeImage) && bitmap == nullptr)) { - SkDebugf("Failed to draw the picture.\n"); - delete bitmap; - return false; - } - - if (FLAGS_validate) { - SkBitmap* referenceBitmap = nullptr; - sk_tools::PictureRenderer* referenceRenderer; - // If the renderer uses a BBoxHierarchy, then the reference renderer - // will be the same renderer, without the bbh. - AutoRestoreBbhType arbbh; - if (sk_tools::PictureRenderer::kNone_BBoxHierarchyType != - renderer.getBBoxHierarchyType()) { - referenceRenderer = &renderer; - referenceRenderer->ref(); // to match auto unref below - arbbh.set(referenceRenderer, sk_tools::PictureRenderer::kNone_BBoxHierarchyType); - } else { -#if SK_SUPPORT_GPU - referenceRenderer = new sk_tools::SimplePictureRenderer(renderer.getGrContextOptions()); -#else - referenceRenderer = new sk_tools::SimplePictureRenderer; -#endif - } - SkAutoTUnref<sk_tools::PictureRenderer> aurReferenceRenderer(referenceRenderer); - - success = render_picture_internal(inputPath, nullptr, nullptr, *referenceRenderer, - &referenceBitmap); - - if (!success || nullptr == referenceBitmap || nullptr == referenceBitmap->getPixels()) { - SkDebugf("Failed to draw the reference picture.\n"); - delete bitmap; - delete referenceBitmap; - return false; - } - - if (success && (bitmap->width() != referenceBitmap->width())) { - SkDebugf("Expected image width: %i, actual image width %i.\n", - referenceBitmap->width(), bitmap->width()); - delete bitmap; - delete referenceBitmap; - return false; - } - if (success && (bitmap->height() != referenceBitmap->height())) { - SkDebugf("Expected image height: %i, actual image height %i", - referenceBitmap->height(), bitmap->height()); - delete bitmap; - delete referenceBitmap; - return false; - } - - for (int y = 0; success && y < bitmap->height(); y++) { - for (int x = 0; success && x < bitmap->width(); x++) { - int diff = MaxByteDiff(*referenceBitmap->getAddr32(x, y), - *bitmap->getAddr32(x, y)); - SkASSERT(diff >= 0 && diff <= 255); - diffs[diff]++; - - if (diff > FLAGS_maxComponentDiff) { - SkDebugf("Expected pixel at (%i %i) exceedds maximum " - "component diff of %i: 0x%x, actual 0x%x\n", - x, y, FLAGS_maxComponentDiff, - *referenceBitmap->getAddr32(x, y), - *bitmap->getAddr32(x, y)); - delete bitmap; - delete referenceBitmap; - return false; - } - } - } - delete referenceBitmap; - - for (int i = 1; i <= 255; ++i) { - if(diffs[i] > 0) { - SkDebugf("Number of pixels with max diff of %i is %i\n", i, diffs[i]); - } - } - } - - if (FLAGS_writeWholeImage) { - sk_tools::force_all_opaque(*bitmap); - - SkString inputFilename = SkOSPath::Basename(inputPath.c_str()); - SkString outputFilename(inputFilename); - sk_tools::replace_char(&outputFilename, '.', '_'); - outputFilename.append(".png"); - - if (jsonSummaryPtr) { - sk_tools::ImageDigest imageDigest(*bitmap); - jsonSummaryPtr->add(inputFilename.c_str(), outputFilename.c_str(), imageDigest); - if ((mismatchPath) && !mismatchPath->isEmpty() && - !jsonSummaryPtr->getExpectation(inputFilename.c_str()).matches(imageDigest)) { - success &= sk_tools::write_bitmap_to_disk(*bitmap, *mismatchPath, nullptr, - outputFilename); - } - } - - if ((writePath) && !writePath->isEmpty()) { - success &= sk_tools::write_bitmap_to_disk(*bitmap, *writePath, nullptr, outputFilename); - } - } - delete bitmap; - - return success; -} - - -static int process_input(const char* input, const SkString* writePath, - const SkString* mismatchPath, sk_tools::PictureRenderer& renderer, - sk_tools::ImageResultsAndExpectations *jsonSummaryPtr) { - SkOSFile::Iter iter(input, "skp"); - SkString inputFilename; - int failures = 0; - SkDebugf("process_input, %s\n", input); - if (iter.next(&inputFilename)) { - do { - SkString inputPath = SkOSPath::Join(input, inputFilename.c_str()); - if (!render_picture(inputPath, writePath, mismatchPath, renderer, jsonSummaryPtr)) { - ++failures; - } - } while(iter.next(&inputFilename)); - } else if (SkStrEndsWith(input, ".skp")) { - SkString inputPath(input); - if (!render_picture(inputPath, writePath, mismatchPath, renderer, jsonSummaryPtr)) { - ++failures; - } - } else { - SkString warning; - warning.printf("Warning: skipping %s\n", input); - SkDebugf("%s", warning.c_str()); - } - return failures; -} - -int tool_main(int argc, char** argv); -int tool_main(int argc, char** argv) { - SkCommandLineFlags::SetUsage("Render .skp files."); - SkCommandLineFlags::Parse(argc, argv); - - if (FLAGS_readPath.isEmpty()) { - SkDebugf(".skp files or directories are required.\n"); - exit(-1); - } - - if (FLAGS_maxComponentDiff < 0 || FLAGS_maxComponentDiff > 256) { - SkDebugf("--maxComponentDiff must be between 0 and 256\n"); - exit(-1); - } - - if (FLAGS_maxComponentDiff != 256 && !FLAGS_validate) { - SkDebugf("--maxComponentDiff requires --validate\n"); - exit(-1); - } - - if (FLAGS_writeEncodedImages) { - if (FLAGS_writePath.isEmpty()) { - SkDebugf("--writeEncodedImages requires --writePath\n"); - exit(-1); - } - if (FLAGS_deferImageDecoding) { - SkDebugf("--writeEncodedImages is not compatible with --deferImageDecoding\n"); - exit(-1); - } - } - - SkString errorString; - SkAutoTUnref<sk_tools::PictureRenderer> renderer(parseRenderer(errorString, - kRender_PictureTool)); - if (errorString.size() > 0) { - SkDebugf("%s\n", errorString.c_str()); - } - - if (renderer.get() == nullptr) { - exit(-1); - } - - SkAutoGraphics ag; - - SkString writePath; - if (FLAGS_writePath.count() == 1) { - writePath.set(FLAGS_writePath[0]); - } - SkString mismatchPath; - if (FLAGS_mismatchPath.count() == 1) { - mismatchPath.set(FLAGS_mismatchPath[0]); - } - sk_tools::ImageResultsAndExpectations jsonSummary; - sk_tools::ImageResultsAndExpectations* jsonSummaryPtr = nullptr; - if (FLAGS_writeJsonSummaryPath.count() == 1) { - jsonSummaryPtr = &jsonSummary; - if (FLAGS_readJsonSummaryPath.count() == 1) { - SkASSERT(jsonSummary.readExpectationsFile(FLAGS_readJsonSummaryPath[0])); - } - } - - int failures = 0; - for (int i = 0; i < FLAGS_readPath.count(); i ++) { - failures += process_input(FLAGS_readPath[i], &writePath, &mismatchPath, *renderer.get(), - jsonSummaryPtr); - } - if (failures != 0) { - SkDebugf("Failed to render %i pictures.\n", failures); - return 1; - } -#if GR_CACHE_STATS && SK_SUPPORT_GPU - if (renderer->isUsingGpuDevice()) { - GrContext* ctx = renderer->getGrContext(); - ctx->printCacheStats(); - } -#endif - -#if GR_GPU_STATS && SK_SUPPORT_GPU - if (FLAGS_gpuStats && renderer->isUsingGpuDevice()) { - renderer->getGrContext()->printGpuStats(); - } -#endif - - if (FLAGS_writeJsonSummaryPath.count() == 1) { - // If there were any descriptions on the command line, insert them now. - for (int i=0; i<FLAGS_descriptions.count(); i++) { - SkTArray<SkString> tokens; - SkStrSplit(FLAGS_descriptions[i], "=", &tokens); - SkASSERT(tokens.count() == 2); - jsonSummary.addDescription(tokens[0].c_str(), tokens[1].c_str()); - } - if (FLAGS_imageBaseGSUrl.count() == 1) { - jsonSummary.setImageBaseGSUrl(FLAGS_imageBaseGSUrl[0]); - } - jsonSummary.writeToFile(FLAGS_writeJsonSummaryPath[0]); - } - return 0; -} - -#if !defined SK_BUILD_FOR_IOS -int main(int argc, char * const argv[]) { - return tool_main(argc, (char**) argv); -} -#endif |