diff --git a/dm/DMCpuTask.cpp b/dm/DMCpuTask.cpp index 14f661ac38..316f3412c5 100644 --- a/dm/DMCpuTask.cpp +++ b/dm/DMCpuTask.cpp @@ -1,6 +1,7 @@ #include "DMCpuTask.h" #include "DMReplayTask.h" #include "DMUtil.h" +#include "DMWriteTask.h" #include "SkCommandLineFlags.h" DEFINE_bool(replay, false, "If true, run replay tests for each CpuTask."); @@ -41,6 +42,7 @@ void CpuTask::draw() { this->spawnChild(SkNEW_ARGS(ReplayTask, ("replay", *this, fGMFactory(NULL), bitmap))); } + this->spawnChild(SkNEW_ARGS(WriteTask, (*this, bitmap))); } bool CpuTask::shouldSkip() const { diff --git a/dm/DMGpuTask.cpp b/dm/DMGpuTask.cpp index 6cf69ffc1c..a002b959d7 100644 --- a/dm/DMGpuTask.cpp +++ b/dm/DMGpuTask.cpp @@ -2,6 +2,7 @@ #include "DMComparisonTask.h" #include "DMUtil.h" +#include "DMWriteTask.h" #include "SkCommandLineFlags.h" #include "SkGpuDevice.h" #include "SkTLS.h" @@ -58,6 +59,7 @@ void GpuTask::draw() { // We offload checksum comparison to the main CPU threadpool. // This cuts run time by about 30%. this->spawnChild(SkNEW_ARGS(ComparisonTask, (*this, fExpectations, bitmap))); + this->spawnChild(SkNEW_ARGS(WriteTask, (*this, bitmap))); } bool GpuTask::shouldSkip() const { diff --git a/dm/DMReplayTask.cpp b/dm/DMReplayTask.cpp index e5f392cee4..0d6780ef42 100644 --- a/dm/DMReplayTask.cpp +++ b/dm/DMReplayTask.cpp @@ -51,4 +51,4 @@ bool ReplayTask::shouldSkip() const { fGM->getFlags() & skiagm::GM::kSkipPicture_Flag; } -} // namespace +} // namespace DM diff --git a/dm/DMReporter.cpp b/dm/DMReporter.cpp index 7a0c20edd3..3d9dae5862 100644 --- a/dm/DMReporter.cpp +++ b/dm/DMReporter.cpp @@ -3,7 +3,13 @@ namespace DM { void Reporter::updateStatusLine() const { - SkDebugf("\r\033[K%d / %d, %d failed", this->finished(), this->started(), this->failed()); + SkString status; + status.printf("\r\033[K%d / %d", this->finished(), this->started()); + const int failed = this->failed(); + if (failed > 0) { + status.appendf(", %d failed", failed); + } + SkDebugf(status.c_str()); } int32_t Reporter::failed() const { diff --git a/dm/DMWriteTask.cpp b/dm/DMWriteTask.cpp new file mode 100644 index 0000000000..21a9b55bc3 --- /dev/null +++ b/dm/DMWriteTask.cpp @@ -0,0 +1,47 @@ +#include "DMWriteTask.h" + +#include "DMUtil.h" +#include "SkCommandLineFlags.h" +#include "SkImageEncoder.h" + +#include + +DEFINE_string2(writePath, w, "", "If set, write GMs here as .pngs."); + +namespace DM { + +WriteTask::WriteTask(const Task& parent, SkBitmap bitmap) + : Task(parent) + , fBitmap(bitmap) { + // Split parent's name _ into gmName and config. + const char* parentName = parent.name().c_str(); + const char* fromLastUnderscore = strrchr(parentName, '_'); + const ptrdiff_t gmNameLength = fromLastUnderscore - parentName; + + fConfig.set(fromLastUnderscore+1); + fGmName.set(parentName, gmNameLength); +} + +void WriteTask::draw() { + const char* root = FLAGS_writePath[0]; + const SkString dir = SkOSPath::SkPathJoin(root, fConfig.c_str()); + if (!sk_mkdir(root) || + !sk_mkdir(dir.c_str()) || + !SkImageEncoder::EncodeFile(png(SkOSPath::SkPathJoin(dir.c_str(), fGmName.c_str())).c_str(), + fBitmap, + SkImageEncoder::kPNG_Type, + 100/*quality*/)) + { + this->fail(); + } +} + +SkString WriteTask::name() const { + return SkStringPrintf("writing %s/%s.png", fConfig.c_str(), fGmName.c_str()); +} + +bool WriteTask::shouldSkip() const { + return FLAGS_writePath.isEmpty(); +} + +} // namespace DM diff --git a/dm/DMWriteTask.h b/dm/DMWriteTask.h new file mode 100644 index 0000000000..7a9b4faf8a --- /dev/null +++ b/dm/DMWriteTask.h @@ -0,0 +1,30 @@ +#ifndef DMWriteTask_DEFINED +#define DMWriteTask_DEFINED + +#include "DMTask.h" +#include "SkBitmap.h" +#include "SkString.h" + +// Writes a bitmap to a file. + +namespace DM { + +class WriteTask : public Task { + +public: + WriteTask(const Task& parent, SkBitmap bitmap); + + virtual void draw() SK_OVERRIDE; + virtual bool usesGpu() const SK_OVERRIDE { return false; } + virtual bool shouldSkip() const SK_OVERRIDE; + virtual SkString name() const SK_OVERRIDE; + +private: + SkString fConfig; + SkString fGmName; + const SkBitmap fBitmap; +}; + +} // namespace DM + +#endif // DMWriteTask_DEFINED diff --git a/dm/README b/dm/README index bce9a7e768..b64fdfbd24 100644 --- a/dm/README +++ b/dm/README @@ -3,7 +3,6 @@ DM is like GM, but multithreaded. It doesn't do everything GM does yet. Current approximate list of missing features: --mismatchPath --missingExpectationsPath - --writePath --writePicturePath --deferred / --pipe diff --git a/gyp/dm.gyp b/gyp/dm.gyp index 315f03b463..bbfea53001 100644 --- a/gyp/dm.gyp +++ b/gyp/dm.gyp @@ -25,6 +25,7 @@ '../dm/DMTask.cpp', '../dm/DMTaskRunner.cpp', '../dm/DMUtil.cpp', + '../dm/DMWriteTask.cpp', '../gm/gm.cpp', '../gm/gm_expectations.cpp',