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
diff --git a/dm/DMQuiltTask.cpp b/dm/DMQuiltTask.cpp
index f184980..44c4341 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 @@
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<SkPicture> 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)));