blob: 815b159a01ee49170d71cfab263d1ba4df02fa09 [file] [log] [blame]
Mike Kleinf5d1a552017-03-25 12:32:22 -04001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Klein58628fd2017-09-21 16:01:07 -04008#include "ProcStats.h"
Mike Klein9a3478b2017-09-29 15:43:28 -04009#include "SkColorFilter.h"
Mike Klein3bf00422017-07-24 14:27:18 -040010#include "SkEventTracingPriv.h"
Florin Malitaab244f02017-05-03 19:16:58 +000011#include "SkImage.h"
Mike Kleine15a7b52017-03-29 12:41:13 -040012#include "SkOSFile.h"
Mike Kleinf5d1a552017-03-25 12:32:22 -040013#include "SkPictureRecorder.h"
Mike Klein39748b22017-05-07 10:52:30 -040014#include "SkPngEncoder.h"
Mike Kleinb323a5e2017-07-24 15:21:31 -040015#include "SkTraceEvent.h"
Mike Klein58628fd2017-09-21 16:01:07 -040016#include "SkTypeface.h"
Mike Klein62669ad2017-05-09 16:03:07 -040017#include "Timer.h"
Mike Kleine15a7b52017-03-29 12:41:13 -040018#include "ok.h"
Mike Klein58628fd2017-09-21 16:01:07 -040019#include "sk_tool_utils.h"
Mike Klein62669ad2017-05-09 16:03:07 -040020#include <chrono>
Mike Kleine15a7b52017-03-29 12:41:13 -040021#include <regex>
Mike Kleinf5d1a552017-03-25 12:32:22 -040022
Mike Kleine15a7b52017-03-29 12:41:13 -040023static std::unique_ptr<Src> proxy(Src* original, std::function<Status(SkCanvas*)> fn) {
Mike Klein0222e702017-03-25 15:53:14 -040024 struct : Src {
Mike Kleine15a7b52017-03-29 12:41:13 -040025 Src* original;
26 std::function<Status(SkCanvas*)> fn;
Mike Klein0222e702017-03-25 15:53:14 -040027
28 std::string name() override { return original->name(); }
29 SkISize size() override { return original->size(); }
Mike Kleine15a7b52017-03-29 12:41:13 -040030 Status draw(SkCanvas* canvas) override { return fn(canvas); }
Mike Klein0222e702017-03-25 15:53:14 -040031 } src;
32 src.original = original;
33 src.fn = fn;
34 return move_unique(src);
35}
36
Mike Kleinf5d1a552017-03-25 12:32:22 -040037struct ViaPic : Dst {
38 std::unique_ptr<Dst> target;
Mike Klein0222e702017-03-25 15:53:14 -040039 bool rtree = false;
Mike Kleinf5d1a552017-03-25 12:32:22 -040040
Mike Klein0222e702017-03-25 15:53:14 -040041 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
42 ViaPic via;
43 via.target = std::move(dst);
44 if (options("bbh") == "rtree") { via.rtree = true; }
45 return move_unique(via);
Mike Kleinf5d1a552017-03-25 12:32:22 -040046 }
47
Mike Kleine15a7b52017-03-29 12:41:13 -040048 Status draw(Src* src) override {
Mike Kleinb323a5e2017-07-24 15:21:31 -040049 TRACE_EVENT0("ok", TRACE_FUNC);
Mike Klein0222e702017-03-25 15:53:14 -040050 SkRTreeFactory factory;
51 SkPictureRecorder rec;
52 rec.beginRecording(SkRect::MakeSize(SkSize::Make(src->size())),
53 rtree ? &factory : nullptr);
Mike Kleinf5d1a552017-03-25 12:32:22 -040054
Mike Klein58628fd2017-09-21 16:01:07 -040055 for (Status status = src->draw(rec.getRecordingCanvas()); status != Status::OK; ) {
Mike Kleine15a7b52017-03-29 12:41:13 -040056 return status;
Mike Klein0222e702017-03-25 15:53:14 -040057 }
Mike Klein58628fd2017-09-21 16:01:07 -040058 sk_sp<SkPicture> pic = rec.finishRecordingAsPicture();
Mike Klein0222e702017-03-25 15:53:14 -040059
60 return target->draw(proxy(src, [=](SkCanvas* canvas) {
61 pic->playback(canvas);
Mike Kleine15a7b52017-03-29 12:41:13 -040062 return Status::OK;
Mike Klein0222e702017-03-25 15:53:14 -040063 }).get());
64 }
65
66 sk_sp<SkImage> image() override {
67 return target->image();
Mike Kleinf5d1a552017-03-25 12:32:22 -040068 }
69};
Mike Kleine15a7b52017-03-29 12:41:13 -040070static Register via_pic{"via_pic", "record then play back an SkPicture", ViaPic::Create};
71
Mike Klein58628fd2017-09-21 16:01:07 -040072// When deserializing, we need to hook this to intercept "Toy Liberation ..."
73// typefaces and return our portable test typeface.
74extern sk_sp<SkTypeface> (*gCreateTypefaceDelegate)(const char[], SkFontStyle);
75
76struct ViaSkp : Dst {
77 std::unique_ptr<Dst> target;
78 bool rtree = false;
79
80 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
81 gCreateTypefaceDelegate = [](const char name[], SkFontStyle style) -> sk_sp<SkTypeface> {
82 if (name == strstr(name, "Toy Liberation")) {
83 return sk_tool_utils::create_portable_typeface(name, style);
84 }
85 return nullptr;
86 };
87
88 ViaSkp via;
89 via.target = std::move(dst);
90 if (options("bbh") == "rtree") { via.rtree = true; }
91 return move_unique(via);
92 }
93
94 Status draw(Src* src) override {
95 TRACE_EVENT0("ok", TRACE_FUNC);
96 SkRTreeFactory factory;
97 SkPictureRecorder rec;
98 rec.beginRecording(SkRect::MakeSize(SkSize::Make(src->size())),
99 rtree ? &factory : nullptr);
100
101 for (Status status = src->draw(rec.getRecordingCanvas()); status != Status::OK; ) {
102 return status;
103 }
104 sk_sp<SkPicture> pic = rec.finishRecordingAsPicture();
105
106 // Serialize and deserialize.
107 pic = SkPicture::MakeFromData(pic->serialize().get());
108
109 return target->draw(proxy(src, [=](SkCanvas* canvas) {
110 pic->playback(canvas);
111 return Status::OK;
112 }).get());
113 }
114
115 sk_sp<SkImage> image() override {
116 return target->image();
117 }
118};
119static Register via_skp{"via_skp", "serialize and deserialize an .skp", ViaSkp::Create};
120
Mike Kleine15a7b52017-03-29 12:41:13 -0400121struct Png : Dst {
122 std::unique_ptr<Dst> target;
123 std::string dir;
124
125 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
126 Png via;
127 via.target = std::move(dst);
128 via.dir = options("dir", "ok");
129 return move_unique(via);
130 }
131
132 Status draw(Src* src) override {
Mike Kleinb323a5e2017-07-24 15:21:31 -0400133 TRACE_EVENT0("ok", TRACE_FUNC);
Mike Kleine15a7b52017-03-29 12:41:13 -0400134 for (auto status = target->draw(src); status != Status::OK; ) {
135 return status;
136 }
137
Mike Klein39748b22017-05-07 10:52:30 -0400138 SkBitmap bm;
Mike Klein9a3478b2017-09-29 15:43:28 -0400139 if (!target->image()->asLegacyBitmap(&bm, SkImage::kRO_LegacyBitmapMode)) {
140 return Status::Failed;
141 }
142
143 // SkPngEncoder can't encode A8 .pngs, and even if it could, they'd be a pain to look at.
144 if (bm.colorType() == kAlpha_8_SkColorType) {
145 SkPaint paint;
146 SkScalar alpha_to_opaque_gray[20] = {
147 0,0,0,1, 0, // red = alpha
148 0,0,0,1, 0, // green = alpha
149 0,0,0,1, 0, // blue = alpha
150 0,0,0,0,255, // alpha = 255
151 };
152 paint.setColorFilter(SkColorFilter::MakeMatrixFilterRowMajor255(alpha_to_opaque_gray));
153 paint.setBlendMode(SkBlendMode::kSrc);
154
155 SkBitmap dst;
156 dst.allocN32Pixels(bm.width(), bm.height(), /*isOpaque=*/true);
157 SkCanvas canvas(dst);
158 canvas.drawBitmap(bm, 0,0, &paint);
159
160 bm = dst;
161 }
162
Mike Klein39748b22017-05-07 10:52:30 -0400163 SkPixmap pm;
Mike Klein9a3478b2017-09-29 15:43:28 -0400164 if (!bm.peekPixels(&pm)) {
Mike Klein39748b22017-05-07 10:52:30 -0400165 return Status::Failed;
166 }
Mike Kleine15a7b52017-03-29 12:41:13 -0400167
168 sk_mkdir(dir.c_str());
Mike Klein39748b22017-05-07 10:52:30 -0400169 SkFILEWStream dst{(dir + "/" + src->name() + ".png").c_str()};
170
171 SkPngEncoder::Options options;
172 options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
173 options.fZLibLevel = 1;
174 options.fUnpremulBehavior = pm.colorSpace() ? SkTransferFunctionBehavior::kRespect
175 : SkTransferFunctionBehavior::kIgnore;
176 return SkPngEncoder::Encode(&dst, pm, options) ? Status::OK
177 : Status::Failed;
Mike Kleine15a7b52017-03-29 12:41:13 -0400178 }
179
180 sk_sp<SkImage> image() override {
181 return target->image();
182 }
183};
184static Register png{"png", "dump PNGs to dir=ok" , Png::Create};
185
186struct Filter : Dst {
187 std::unique_ptr<Dst> target;
188 std::regex match, search;
189
190 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
191 Filter via;
192 via.target = std::move(dst);
193 via.match = options("match", ".*");
194 via.search = options("search", ".*");
195 return move_unique(via);
196 }
197
198 Status draw(Src* src) override {
199 auto name = src->name();
200 if (!std::regex_match (name, match) ||
201 !std::regex_search(name, search)) {
202 return Status::Skipped;
203 }
204 return target->draw(src);
205 }
206
207 sk_sp<SkImage> image() override {
208 return target->image();
209 }
210};
Mike Klein452a7a22017-05-09 18:04:04 -0400211static Register filter{"filter",
Mike Kleine15a7b52017-03-29 12:41:13 -0400212 "run only srcs matching match=.* exactly and search=.* somewhere",
213 Filter::Create};
Mike Klein62669ad2017-05-09 16:03:07 -0400214
215struct Time : Dst {
216 std::unique_ptr<Dst> target;
217
218 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
219 Time via;
220 via.target = std::move(dst);
221 return move_unique(via);
222 }
223
224 Status draw(Src* src) override {
225 auto start = std::chrono::steady_clock::now();
226 Status status = target->draw(src);
227 std::chrono::duration<double, std::milli> elapsed = std::chrono::steady_clock::now()
228 - start;
229
Mike Klein1431e5e2017-07-24 13:20:30 -0400230 if (status != Status::Skipped) {
231 auto msg = HumanizeMs(elapsed.count());
232 ok_log(msg.c_str());
233 }
Mike Klein62669ad2017-05-09 16:03:07 -0400234 return status;
235 }
236
237 sk_sp<SkImage> image() override {
238 return target->image();
239 }
240};
Mike Klein99609bb2017-06-19 12:05:31 -0700241static Register _time{"time", "print wall run time", Time::Create};
242
243struct Memory : Dst {
244 std::unique_ptr<Dst> target;
245
246 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
247 Memory via;
248 via.target = std::move(dst);
249 return move_unique(via);
250 }
251
252 Status draw(Src* src) override {
253 Status status = target->draw(src);
254
Mike Klein1431e5e2017-07-24 13:20:30 -0400255 if (status != Status::Skipped) {
256 auto msg = SkStringPrintf("%dMB", sk_tools::getMaxResidentSetSizeMB());
257 ok_log(msg.c_str());
258 }
Mike Klein99609bb2017-06-19 12:05:31 -0700259
260 return status;
261 }
262
263 sk_sp<SkImage> image() override {
264 return target->image();
265 }
266};
267static Register memory{"memory", "print process maximum memory usage", Memory::Create};
Mike Klein3bf00422017-07-24 14:27:18 -0400268
269static SkOnce init_tracing_once;
270struct Trace : Dst {
271 std::unique_ptr<Dst> target;
272 std::string trace_mode;
273
274 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
275 Trace via;
276 via.target = std::move(dst);
277 via.trace_mode = options("mode", "trace.json");
278 return move_unique(via);
279 }
280
281 Status draw(Src* src) override {
282 init_tracing_once([&] { initializeEventTracingForTools(trace_mode.c_str()); });
283 return target->draw(src);
284 }
285
286 sk_sp<SkImage> image() override {
287 return target->image();
288 }
289};
290static Register trace {"trace",
291 "enable tracing in mode=atrace, mode=debugf, or mode=trace.json",
292 Trace::Create};