Add multithreaded mode to quilt mode in DM.
authormtklein <mtklein@chromium.org>
Tue, 1 Jul 2014 14:46:50 +0000 (07:46 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 1 Jul 2014 14:46:50 +0000 (07:46 -0700)
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

index f184980..44c4341 100644 (file)
@@ -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<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);
-
-    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*/);
+    SkThreadPool pool(FLAGS_quiltThreaded ? SkThreadPool::kThreadPerCore : 0);
 
-            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)));