blob: 162522346f711232c07701f19d13205659b39998 [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 Klein361dde02017-11-07 08:14:52 -05008#include "../dm/DMFontMgr.h"
Mike Klein58628fd2017-09-21 16:01:07 -04009#include "ProcStats.h"
Mike Klein9a3478b2017-09-29 15:43:28 -040010#include "SkColorFilter.h"
Mike Klein3bf00422017-07-24 14:27:18 -040011#include "SkEventTracingPriv.h"
Florin Malitaab244f02017-05-03 19:16:58 +000012#include "SkImage.h"
Mike Kleine15a7b52017-03-29 12:41:13 -040013#include "SkOSFile.h"
Mike Kleinf5d1a552017-03-25 12:32:22 -040014#include "SkPictureRecorder.h"
Mike Klein39748b22017-05-07 10:52:30 -040015#include "SkPngEncoder.h"
Mike Kleinb323a5e2017-07-24 15:21:31 -040016#include "SkTraceEvent.h"
Mike Klein58628fd2017-09-21 16:01:07 -040017#include "SkTypeface.h"
Mike Klein62669ad2017-05-09 16:03:07 -040018#include "Timer.h"
Mike Kleine15a7b52017-03-29 12:41:13 -040019#include "ok.h"
Mike Klein58628fd2017-09-21 16:01:07 -040020#include "sk_tool_utils.h"
Mike Klein62669ad2017-05-09 16:03:07 -040021#include <chrono>
Mike Kleine15a7b52017-03-29 12:41:13 -040022#include <regex>
Mike Kleinf5d1a552017-03-25 12:32:22 -040023
Mike Kleine15a7b52017-03-29 12:41:13 -040024static std::unique_ptr<Src> proxy(Src* original, std::function<Status(SkCanvas*)> fn) {
Mike Klein0222e702017-03-25 15:53:14 -040025 struct : Src {
Mike Kleine15a7b52017-03-29 12:41:13 -040026 Src* original;
27 std::function<Status(SkCanvas*)> fn;
Mike Klein0222e702017-03-25 15:53:14 -040028
29 std::string name() override { return original->name(); }
30 SkISize size() override { return original->size(); }
Mike Kleine15a7b52017-03-29 12:41:13 -040031 Status draw(SkCanvas* canvas) override { return fn(canvas); }
Mike Klein0222e702017-03-25 15:53:14 -040032 } src;
33 src.original = original;
34 src.fn = fn;
35 return move_unique(src);
36}
37
Mike Kleinf5d1a552017-03-25 12:32:22 -040038struct ViaPic : Dst {
39 std::unique_ptr<Dst> target;
Mike Klein0222e702017-03-25 15:53:14 -040040 bool rtree = false;
Mike Kleinf5d1a552017-03-25 12:32:22 -040041
Mike Klein0222e702017-03-25 15:53:14 -040042 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
43 ViaPic via;
44 via.target = std::move(dst);
45 if (options("bbh") == "rtree") { via.rtree = true; }
46 return move_unique(via);
Mike Kleinf5d1a552017-03-25 12:32:22 -040047 }
48
Mike Kleine15a7b52017-03-29 12:41:13 -040049 Status draw(Src* src) override {
Mike Kleinb323a5e2017-07-24 15:21:31 -040050 TRACE_EVENT0("ok", TRACE_FUNC);
Mike Klein0222e702017-03-25 15:53:14 -040051 SkRTreeFactory factory;
52 SkPictureRecorder rec;
53 rec.beginRecording(SkRect::MakeSize(SkSize::Make(src->size())),
54 rtree ? &factory : nullptr);
Mike Kleinf5d1a552017-03-25 12:32:22 -040055
Mike Klein58628fd2017-09-21 16:01:07 -040056 for (Status status = src->draw(rec.getRecordingCanvas()); status != Status::OK; ) {
Mike Kleine15a7b52017-03-29 12:41:13 -040057 return status;
Mike Klein0222e702017-03-25 15:53:14 -040058 }
Mike Klein58628fd2017-09-21 16:01:07 -040059 sk_sp<SkPicture> pic = rec.finishRecordingAsPicture();
Mike Klein0222e702017-03-25 15:53:14 -040060
61 return target->draw(proxy(src, [=](SkCanvas* canvas) {
62 pic->playback(canvas);
Mike Kleine15a7b52017-03-29 12:41:13 -040063 return Status::OK;
Mike Klein0222e702017-03-25 15:53:14 -040064 }).get());
65 }
66
67 sk_sp<SkImage> image() override {
68 return target->image();
Mike Kleinf5d1a552017-03-25 12:32:22 -040069 }
70};
Mike Kleine15a7b52017-03-29 12:41:13 -040071static Register via_pic{"via_pic", "record then play back an SkPicture", ViaPic::Create};
72
Mike Klein58628fd2017-09-21 16:01:07 -040073// When deserializing, we need to hook this to intercept "Toy Liberation ..."
74// typefaces and return our portable test typeface.
75extern sk_sp<SkTypeface> (*gCreateTypefaceDelegate)(const char[], SkFontStyle);
76
77struct ViaSkp : Dst {
78 std::unique_ptr<Dst> target;
79 bool rtree = false;
80
81 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
82 gCreateTypefaceDelegate = [](const char name[], SkFontStyle style) -> sk_sp<SkTypeface> {
83 if (name == strstr(name, "Toy Liberation")) {
84 return sk_tool_utils::create_portable_typeface(name, style);
85 }
86 return nullptr;
87 };
88
89 ViaSkp via;
90 via.target = std::move(dst);
91 if (options("bbh") == "rtree") { via.rtree = true; }
92 return move_unique(via);
93 }
94
95 Status draw(Src* src) override {
96 TRACE_EVENT0("ok", TRACE_FUNC);
97 SkRTreeFactory factory;
98 SkPictureRecorder rec;
99 rec.beginRecording(SkRect::MakeSize(SkSize::Make(src->size())),
100 rtree ? &factory : nullptr);
101
102 for (Status status = src->draw(rec.getRecordingCanvas()); status != Status::OK; ) {
103 return status;
104 }
105 sk_sp<SkPicture> pic = rec.finishRecordingAsPicture();
106
107 // Serialize and deserialize.
108 pic = SkPicture::MakeFromData(pic->serialize().get());
109
110 return target->draw(proxy(src, [=](SkCanvas* canvas) {
111 pic->playback(canvas);
112 return Status::OK;
113 }).get());
114 }
115
116 sk_sp<SkImage> image() override {
117 return target->image();
118 }
119};
120static Register via_skp{"via_skp", "serialize and deserialize an .skp", ViaSkp::Create};
121
Mike Kleine15a7b52017-03-29 12:41:13 -0400122struct Png : Dst {
123 std::unique_ptr<Dst> target;
124 std::string dir;
125
126 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
127 Png via;
128 via.target = std::move(dst);
129 via.dir = options("dir", "ok");
130 return move_unique(via);
131 }
132
133 Status draw(Src* src) override {
Mike Kleinb323a5e2017-07-24 15:21:31 -0400134 TRACE_EVENT0("ok", TRACE_FUNC);
Mike Kleine15a7b52017-03-29 12:41:13 -0400135 for (auto status = target->draw(src); status != Status::OK; ) {
136 return status;
137 }
138
Mike Klein39748b22017-05-07 10:52:30 -0400139 SkBitmap bm;
Mike Klein9a3478b2017-09-29 15:43:28 -0400140 if (!target->image()->asLegacyBitmap(&bm, SkImage::kRO_LegacyBitmapMode)) {
141 return Status::Failed;
142 }
143
144 // SkPngEncoder can't encode A8 .pngs, and even if it could, they'd be a pain to look at.
145 if (bm.colorType() == kAlpha_8_SkColorType) {
146 SkPaint paint;
147 SkScalar alpha_to_opaque_gray[20] = {
148 0,0,0,1, 0, // red = alpha
149 0,0,0,1, 0, // green = alpha
150 0,0,0,1, 0, // blue = alpha
151 0,0,0,0,255, // alpha = 255
152 };
153 paint.setColorFilter(SkColorFilter::MakeMatrixFilterRowMajor255(alpha_to_opaque_gray));
154 paint.setBlendMode(SkBlendMode::kSrc);
155
156 SkBitmap dst;
157 dst.allocN32Pixels(bm.width(), bm.height(), /*isOpaque=*/true);
158 SkCanvas canvas(dst);
159 canvas.drawBitmap(bm, 0,0, &paint);
160
161 bm = dst;
162 }
163
Mike Klein39748b22017-05-07 10:52:30 -0400164 SkPixmap pm;
Mike Klein9a3478b2017-09-29 15:43:28 -0400165 if (!bm.peekPixels(&pm)) {
Mike Klein39748b22017-05-07 10:52:30 -0400166 return Status::Failed;
167 }
Mike Kleine15a7b52017-03-29 12:41:13 -0400168
169 sk_mkdir(dir.c_str());
Mike Klein39748b22017-05-07 10:52:30 -0400170 SkFILEWStream dst{(dir + "/" + src->name() + ".png").c_str()};
171
172 SkPngEncoder::Options options;
173 options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;
174 options.fZLibLevel = 1;
175 options.fUnpremulBehavior = pm.colorSpace() ? SkTransferFunctionBehavior::kRespect
176 : SkTransferFunctionBehavior::kIgnore;
177 return SkPngEncoder::Encode(&dst, pm, options) ? Status::OK
178 : Status::Failed;
Mike Kleine15a7b52017-03-29 12:41:13 -0400179 }
180
181 sk_sp<SkImage> image() override {
182 return target->image();
183 }
184};
185static Register png{"png", "dump PNGs to dir=ok" , Png::Create};
186
187struct Filter : Dst {
188 std::unique_ptr<Dst> target;
189 std::regex match, search;
190
191 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
192 Filter via;
193 via.target = std::move(dst);
194 via.match = options("match", ".*");
195 via.search = options("search", ".*");
196 return move_unique(via);
197 }
198
199 Status draw(Src* src) override {
200 auto name = src->name();
201 if (!std::regex_match (name, match) ||
202 !std::regex_search(name, search)) {
203 return Status::Skipped;
204 }
205 return target->draw(src);
206 }
207
208 sk_sp<SkImage> image() override {
209 return target->image();
210 }
211};
Mike Klein452a7a22017-05-09 18:04:04 -0400212static Register filter{"filter",
Mike Kleine15a7b52017-03-29 12:41:13 -0400213 "run only srcs matching match=.* exactly and search=.* somewhere",
214 Filter::Create};
Mike Klein62669ad2017-05-09 16:03:07 -0400215
216struct Time : Dst {
217 std::unique_ptr<Dst> target;
218
219 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
220 Time via;
221 via.target = std::move(dst);
222 return move_unique(via);
223 }
224
225 Status draw(Src* src) override {
226 auto start = std::chrono::steady_clock::now();
227 Status status = target->draw(src);
228 std::chrono::duration<double, std::milli> elapsed = std::chrono::steady_clock::now()
229 - start;
230
Mike Klein1431e5e2017-07-24 13:20:30 -0400231 if (status != Status::Skipped) {
232 auto msg = HumanizeMs(elapsed.count());
233 ok_log(msg.c_str());
234 }
Mike Klein62669ad2017-05-09 16:03:07 -0400235 return status;
236 }
237
238 sk_sp<SkImage> image() override {
239 return target->image();
240 }
241};
Mike Klein99609bb2017-06-19 12:05:31 -0700242static Register _time{"time", "print wall run time", Time::Create};
243
244struct Memory : Dst {
245 std::unique_ptr<Dst> target;
246
247 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
248 Memory via;
249 via.target = std::move(dst);
250 return move_unique(via);
251 }
252
253 Status draw(Src* src) override {
254 Status status = target->draw(src);
255
Mike Klein1431e5e2017-07-24 13:20:30 -0400256 if (status != Status::Skipped) {
257 auto msg = SkStringPrintf("%dMB", sk_tools::getMaxResidentSetSizeMB());
258 ok_log(msg.c_str());
259 }
Mike Klein99609bb2017-06-19 12:05:31 -0700260
261 return status;
262 }
263
264 sk_sp<SkImage> image() override {
265 return target->image();
266 }
267};
268static Register memory{"memory", "print process maximum memory usage", Memory::Create};
Mike Klein3bf00422017-07-24 14:27:18 -0400269
Mike Klein3bf00422017-07-24 14:27:18 -0400270struct 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 {
Mike Klein361dde02017-11-07 08:14:52 -0500282 static SkOnce once;
283 once([&] { initializeEventTracingForTools(trace_mode.c_str()); });
Mike Klein3bf00422017-07-24 14:27:18 -0400284 return target->draw(src);
285 }
286
287 sk_sp<SkImage> image() override {
288 return target->image();
289 }
290};
Mike Klein361dde02017-11-07 08:14:52 -0500291static Register trace{"trace",
292 "enable tracing in mode=atrace, mode=debugf, or mode=trace.json",
293 Trace::Create};
294
295extern sk_sp<SkFontMgr> (*gSkFontMgr_DefaultFactory)();
296
297struct PortableFonts : Dst {
298 std::unique_ptr<Dst> target;
299
300 static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
301 PortableFonts via;
302 via.target = std::move(dst);
303 return move_unique(via);
304 }
305
306 Status draw(Src* src) override {
307 static SkOnce once;
308 once([]{
309 gSkFontMgr_DefaultFactory = []() -> sk_sp<SkFontMgr> {
310 return sk_make_sp<DM::FontMgr>();
311 };
312 });
313 return target->draw(src);
314 }
315
316 sk_sp<SkImage> image() override {
317 return target->image();
318 }
319};
320static Register portable_fonts{"portable_fonts",
321 "use DM::FontMgr to make fonts more portable",
322 PortableFonts::Create};