blob: 04f59992fcd88de3cfd4b48ed6babb800eebb96e [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
mtkleine4636aa2014-07-09 13:10:58 -070013static const char* kSuffixes[] = { "nobbh", "rtree", "quadtree", "tilegrid", "skr" };
mtklein7cdc1ee2014-07-07 10:41:04 -070014
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000015namespace DM {
16
mtklein7cdc1ee2014-07-07 10:41:04 -070017QuiltTask::QuiltTask(const Task& parent, skiagm::GM* gm, SkBitmap reference, QuiltTask::Mode mode)
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000018 : CpuTask(parent)
mtklein7cdc1ee2014-07-07 10:41:04 -070019 , fMode(mode)
20 , fName(UnderJoin(parent.name().c_str(), kSuffixes[mode]))
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000021 , fGM(gm)
22 , fReference(reference)
23 {}
24
25static int tiles_needed(int fullDimension, int tileDimension) {
26 return (fullDimension + tileDimension - 1) / tileDimension;
27}
28
mtkleinec2ae582014-07-01 07:46:50 -070029class Tile : public SkRunnable {
30public:
mtklein7cdc1ee2014-07-07 10:41:04 -070031 Tile(int x, int y, const SkPicture& picture, SkBitmap* quilt)
32 : fX(x * FLAGS_quiltTile)
33 , fY(y * FLAGS_quiltTile)
mtkleinec2ae582014-07-01 07:46:50 -070034 , fPicture(picture)
mtklein7cdc1ee2014-07-07 10:41:04 -070035 , fQuilt(quilt) {}
mtkleinec2ae582014-07-01 07:46:50 -070036
37 virtual void run() SK_OVERRIDE {
38 SkBitmap tile;
mtklein7cdc1ee2014-07-07 10:41:04 -070039 fQuilt->extractSubset(&tile, SkIRect::MakeXYWH(fX, fY, FLAGS_quiltTile, FLAGS_quiltTile));
mtkleinec2ae582014-07-01 07:46:50 -070040 SkCanvas tileCanvas(tile);
41
mtklein7cdc1ee2014-07-07 10:41:04 -070042 tileCanvas.translate(SkIntToScalar(-fX), SkIntToScalar(-fY));
mtkleinec2ae582014-07-01 07:46:50 -070043 fPicture.draw(&tileCanvas);
44 tileCanvas.flush();
45
mtkleinec2ae582014-07-01 07:46:50 -070046 delete this;
47 }
48
49private:
50 const int fX, fY;
mtkleinec2ae582014-07-01 07:46:50 -070051 const SkPicture& fPicture;
mtklein7cdc1ee2014-07-07 10:41:04 -070052 SkBitmap* fQuilt;
mtkleinec2ae582014-07-01 07:46:50 -070053};
54
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000055void QuiltTask::draw() {
mtkleine4636aa2014-07-09 13:10:58 -070056 SkAutoTDelete<SkBBHFactory> factory;
57 switch (fMode) {
58 case kRTree_Mode:
59 factory.reset(SkNEW(SkRTreeFactory));
60 break;
61 case kQuadTree_Mode:
62 factory.reset(SkNEW(SkQuadTreeFactory));
63 break;
64 case kTileGrid_Mode: {
65 const SkTileGridFactory::TileGridInfo tiles = {
66 { FLAGS_quiltTile, FLAGS_quiltTile },
67 /*overlap: */{0, 0},
68 /*offset: */{0, 0},
69 };
70 factory.reset(SkNEW_ARGS(SkTileGridFactory, (tiles)));
71 break;
72 }
73
74 case kNoBBH_Mode:
75 case kSkRecord_Mode:
76 break;
77 }
78
79 // A couple GMs draw wrong when using a bounding box hierarchy.
80 // This almost certainly means we have a bug to fix, but for now
81 // just draw without a bounding box hierarchy.
82 if (fGM->getFlags() & skiagm::GM::kNoBBH_Flag) {
83 factory.reset(NULL);
84 }
85
86 SkAutoTUnref<const SkPicture> recorded(
87 RecordPicture(fGM.get(), factory.get(), kSkRecord_Mode == fMode));
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000088
89 SkBitmap full;
commit-bot@chromium.org26642072014-05-15 17:33:31 +000090 AllocatePixels(fReference, &full);
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000091
mtkleine4636aa2014-07-09 13:10:58 -070092 if (fGM->getFlags() & skiagm::GM::kSkipTiled_Flag) {
93 // Some GMs don't draw exactly the same when tiled. Draw them in one go.
94 SkCanvas canvas(full);
95 recorded->draw(&canvas);
96 canvas.flush();
97 } else {
98 // Draw tiles in parallel into the same bitmap, simulating aggressive impl-side painting.
99 SkThreadPool pool(SkThreadPool::kThreadPerCore);
100 for (int y = 0; y < tiles_needed(full.height(), FLAGS_quiltTile); y++) {
101 for (int x = 0; x < tiles_needed(full.width(), FLAGS_quiltTile); x++) {
102 // Deletes itself when done.
103 pool.add(new Tile(x, y, *recorded, &full));
104 }
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000105 }
106 }
107
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000108 if (!BitmapsEqual(full, fReference)) {
109 this->fail();
110 this->spawnChild(SkNEW_ARGS(WriteTask, (*this, full)));
111 }
112}
113
114bool QuiltTask::shouldSkip() const {
115 if (fGM->getFlags() & skiagm::GM::kSkipPicture_Flag) {
116 return true;
117 }
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000118 return !FLAGS_quilt;
119}
120
121} // namespace DM