From ec2ae5878d0c4fe3492b6866eaa3b946e526f1a3 Mon Sep 17 00:00:00 2001 From: mtklein Date: Tue, 1 Jul 2014 07:46:50 -0700 Subject: [PATCH] Add multithreaded mode to quilt mode in DM. Default off for now. Something to work toward. BUG=skia: R=robertphillips@google.com, tomhudson@chromium.org, mtklein@google.com Author: mtklein@chromium.org Review URL: https://codereview.chromium.org/360793002 --- dm/DMQuiltTask.cpp | 67 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/dm/DMQuiltTask.cpp b/dm/DMQuiltTask.cpp index f184980c1d..44c4341a7d 100644 --- a/dm/DMQuiltTask.cpp +++ b/dm/DMQuiltTask.cpp @@ -4,9 +4,11 @@ #include "SkCommandLineFlags.h" #include "SkPicture.h" +#include "SkThreadPool.h" DEFINE_bool(quilt, true, "If true, draw into a quilt of small tiles and compare."); DEFINE_int32(quiltTile, 16, "Dimension of (square) quilt tile."); +DEFINE_bool(quiltThreaded, false, "If true, draw quilt tiles with multiple threads."); namespace DM { @@ -21,34 +23,65 @@ static int tiles_needed(int fullDimension, int tileDimension) { return (fullDimension + tileDimension - 1) / tileDimension; } +class Tile : public SkRunnable { +public: + Tile(int x, int y, SkColorType colorType, + const SkPicture& picture, SkCanvas* canvas, SkMutex* mutex) + : fX(x) + , fY(y) + , fColorType(colorType) + , fPicture(picture) + , fCanvas(canvas) + , fMutex(mutex) {} + + virtual void run() SK_OVERRIDE { + SkBitmap tile; + tile.allocPixels(SkImageInfo::Make(FLAGS_quiltTile, FLAGS_quiltTile, + fColorType, kPremul_SkAlphaType)); + SkCanvas tileCanvas(tile); + + const SkScalar xOffset = SkIntToScalar(fX * tile.width()), + yOffset = SkIntToScalar(fY * tile.height()); + tileCanvas.translate(-xOffset, -yOffset); + fPicture.draw(&tileCanvas); + tileCanvas.flush(); + + { + SkAutoMutexAcquire lock(fMutex); + fCanvas->drawBitmap(tile, xOffset, yOffset, NULL); + } + + delete this; + } + +private: + const int fX, fY; + const SkColorType fColorType; + const SkPicture& fPicture; + SkCanvas* fCanvas; + SkMutex* fMutex; // Guards fCanvas. +}; + void QuiltTask::draw() { SkAutoTUnref recorded(RecordPicture(fGM.get())); SkBitmap full; AllocatePixels(fReference, &full); SkCanvas fullCanvas(full); + SkMutex mutex; // Guards fullCanvas. - SkBitmap tile; - tile.allocPixels(SkImageInfo::Make(FLAGS_quiltTile, FLAGS_quiltTile, - fReference.colorType(), kPremul_SkAlphaType)); - SkCanvas tileCanvas(tile); + SkThreadPool pool(FLAGS_quiltThreaded ? SkThreadPool::kThreadPerCore : 0); - for (int y = 0; y < tiles_needed(full.height(), tile.height()); y++) { - for (int x = 0; x < tiles_needed(full.width(), tile.width()); x++) { - SkAutoCanvasRestore ar(&tileCanvas, true/*also save now*/); - - const SkScalar xOffset = SkIntToScalar(x * tile.width()), - yOffset = SkIntToScalar(y * tile.height()); - SkMatrix matrix = tileCanvas.getTotalMatrix(); - matrix.postTranslate(-xOffset, -yOffset); - tileCanvas.setMatrix(matrix); - - recorded->draw(&tileCanvas); - tileCanvas.flush(); - fullCanvas.drawBitmap(tile, xOffset, yOffset, NULL); + for (int y = 0; y < tiles_needed(full.height(), FLAGS_quiltTile); y++) { + for (int x = 0; x < tiles_needed(full.width(), FLAGS_quiltTile); x++) { + // Deletes itself when done. + pool.add(new Tile(x, y, fReference.colorType(), *recorded, &fullCanvas, &mutex)); } } + pool.wait(); + fullCanvas.flush(); + if (!BitmapsEqual(full, fReference)) { this->fail(); this->spawnChild(SkNEW_ARGS(WriteTask, (*this, full)));