blob: 469b20f433fe8175d8357a5f6e2a7b00775a83e3 [file] [log] [blame]
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +00001#include "DMQuiltTask.h"
2#include "DMUtil.h"
3#include "DMWriteTask.h"
4
mtkleine4636aa2014-07-09 13:10:58 -07005#include "SkBBHFactory.h"
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +00006#include "SkCommandLineFlags.h"
7#include "SkPicture.h"
mtkleinec2ae582014-07-01 07:46:50 -07008#include "SkThreadPool.h"
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +00009
mtkleine4636aa2014-07-09 13:10:58 -070010DEFINE_bool(quilt, true, "If true, draw GM via a picture into a quilt of small tiles and compare.");
mtklein7cdc1ee2014-07-07 10:41:04 -070011DEFINE_int32(quiltTile, 256, "Dimension of (square) quilt tile.");
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000012
13namespace DM {
14
mtklein5ad6ee12014-08-11 08:08:43 -070015static SkString suffix(QuiltTask::Backend backend, QuiltTask::BBH bbh) {
16 static const char* kBackends[] = { "default", "skrecord" };
17 static const char* kBBHs[] = { "nobbh", "rtree", "quadtree", "tilegrid" };
18 return SkStringPrintf("%s-%s", kBackends[backend], kBBHs[bbh]);
19}
20
21QuiltTask::QuiltTask(const Task& parent, skiagm::GM* gm, SkBitmap reference,
22 QuiltTask::BBH bbh, QuiltTask::Backend backend)
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000023 : CpuTask(parent)
mtklein5ad6ee12014-08-11 08:08:43 -070024 , fBBH(bbh)
25 , fBackend(backend)
26 , fName(UnderJoin(parent.name().c_str(), suffix(backend, bbh).c_str()))
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000027 , fGM(gm)
28 , fReference(reference)
29 {}
30
31static int tiles_needed(int fullDimension, int tileDimension) {
32 return (fullDimension + tileDimension - 1) / tileDimension;
33}
34
mtkleinec2ae582014-07-01 07:46:50 -070035class Tile : public SkRunnable {
36public:
mtklein7cdc1ee2014-07-07 10:41:04 -070037 Tile(int x, int y, const SkPicture& picture, SkBitmap* quilt)
38 : fX(x * FLAGS_quiltTile)
39 , fY(y * FLAGS_quiltTile)
mtkleinec2ae582014-07-01 07:46:50 -070040 , fPicture(picture)
mtklein7cdc1ee2014-07-07 10:41:04 -070041 , fQuilt(quilt) {}
mtkleinec2ae582014-07-01 07:46:50 -070042
43 virtual void run() SK_OVERRIDE {
44 SkBitmap tile;
mtklein7cdc1ee2014-07-07 10:41:04 -070045 fQuilt->extractSubset(&tile, SkIRect::MakeXYWH(fX, fY, FLAGS_quiltTile, FLAGS_quiltTile));
mtkleinec2ae582014-07-01 07:46:50 -070046 SkCanvas tileCanvas(tile);
47
mtklein7cdc1ee2014-07-07 10:41:04 -070048 tileCanvas.translate(SkIntToScalar(-fX), SkIntToScalar(-fY));
mtkleinec2ae582014-07-01 07:46:50 -070049 fPicture.draw(&tileCanvas);
50 tileCanvas.flush();
51
mtkleinec2ae582014-07-01 07:46:50 -070052 delete this;
53 }
54
55private:
56 const int fX, fY;
mtkleinec2ae582014-07-01 07:46:50 -070057 const SkPicture& fPicture;
mtklein7cdc1ee2014-07-07 10:41:04 -070058 SkBitmap* fQuilt;
mtkleinec2ae582014-07-01 07:46:50 -070059};
60
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000061void QuiltTask::draw() {
mtkleine4636aa2014-07-09 13:10:58 -070062 SkAutoTDelete<SkBBHFactory> factory;
mtklein5ad6ee12014-08-11 08:08:43 -070063 switch (fBBH) {
64 case kNone_BBH: break;
65 case kRTree_BBH:
mtkleine4636aa2014-07-09 13:10:58 -070066 factory.reset(SkNEW(SkRTreeFactory));
67 break;
mtklein5ad6ee12014-08-11 08:08:43 -070068 case kQuadTree_BBH:
mtkleine4636aa2014-07-09 13:10:58 -070069 factory.reset(SkNEW(SkQuadTreeFactory));
70 break;
mtklein5ad6ee12014-08-11 08:08:43 -070071 case kTileGrid_BBH: {
mtkleine4636aa2014-07-09 13:10:58 -070072 const SkTileGridFactory::TileGridInfo tiles = {
73 { FLAGS_quiltTile, FLAGS_quiltTile },
74 /*overlap: */{0, 0},
75 /*offset: */{0, 0},
76 };
77 factory.reset(SkNEW_ARGS(SkTileGridFactory, (tiles)));
78 break;
79 }
mtkleine4636aa2014-07-09 13:10:58 -070080 }
81
82 // A couple GMs draw wrong when using a bounding box hierarchy.
83 // This almost certainly means we have a bug to fix, but for now
84 // just draw without a bounding box hierarchy.
85 if (fGM->getFlags() & skiagm::GM::kNoBBH_Flag) {
86 factory.reset(NULL);
87 }
88
89 SkAutoTUnref<const SkPicture> recorded(
mtklein5ad6ee12014-08-11 08:08:43 -070090 RecordPicture(fGM.get(), factory.get(), kSkRecord_Backend == fBackend));
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000091
92 SkBitmap full;
commit-bot@chromium.org26642072014-05-15 17:33:31 +000093 AllocatePixels(fReference, &full);
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000094
mtkleine4636aa2014-07-09 13:10:58 -070095 if (fGM->getFlags() & skiagm::GM::kSkipTiled_Flag) {
96 // Some GMs don't draw exactly the same when tiled. Draw them in one go.
97 SkCanvas canvas(full);
98 recorded->draw(&canvas);
99 canvas.flush();
100 } else {
101 // Draw tiles in parallel into the same bitmap, simulating aggressive impl-side painting.
102 SkThreadPool pool(SkThreadPool::kThreadPerCore);
103 for (int y = 0; y < tiles_needed(full.height(), FLAGS_quiltTile); y++) {
104 for (int x = 0; x < tiles_needed(full.width(), FLAGS_quiltTile); x++) {
105 // Deletes itself when done.
106 pool.add(new Tile(x, y, *recorded, &full));
107 }
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000108 }
109 }
110
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000111 if (!BitmapsEqual(full, fReference)) {
112 this->fail();
113 this->spawnChild(SkNEW_ARGS(WriteTask, (*this, full)));
114 }
115}
116
117bool QuiltTask::shouldSkip() const {
118 if (fGM->getFlags() & skiagm::GM::kSkipPicture_Flag) {
119 return true;
120 }
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000121 return !FLAGS_quilt;
122}
123
124} // namespace DM