blob: 9793663b6f3c4dd70999007508ec57e62544d832 [file] [log] [blame]
halcanary1abea462016-02-24 09:25:58 -08001/*
2 * Copyright 2016 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
8#include "Benchmark.h"
Hal Canary43fb7a02016-12-30 13:09:03 -05009
halcanary1abea462016-02-24 09:25:58 -080010#include "Resources.h"
robertphillipsc5035e72016-03-17 06:58:39 -070011#include "SkAutoPixmapStorage.h"
halcanary1abea462016-02-24 09:25:58 -080012#include "SkData.h"
Hal Canary3c36ef62018-01-02 16:25:53 -050013#include "SkFloatToDecimal.h"
halcanaryd11c7262016-03-25 05:52:57 -070014#include "SkGradientShader.h"
halcanary1e440512016-02-24 15:17:19 -080015#include "SkImage.h"
halcanary1e440512016-02-24 15:17:19 -080016#include "SkPixmap.h"
halcanarycf430132016-03-09 10:49:23 -080017#include "SkRandom.h"
halcanarycbc060a2016-04-11 19:41:48 -070018#include "SkStream.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040019#include "SkTo.h"
halcanary1abea462016-02-24 09:25:58 -080020
21namespace {
Hal Canary43fb7a02016-12-30 13:09:03 -050022struct WStreamWriteTextBenchmark : public Benchmark {
23 std::unique_ptr<SkWStream> fWStream;
Mike Reed2a65cc02017-03-22 10:01:53 -040024 WStreamWriteTextBenchmark() : fWStream(new SkNullWStream) {}
Hal Canary43fb7a02016-12-30 13:09:03 -050025 const char* onGetName() override { return "WStreamWriteText"; }
26 bool isSuitableFor(Backend backend) override {
27 return backend == kNonRendering_Backend;
28 }
29 void onDraw(int loops, SkCanvas*) override {
30 while (loops-- > 0) {
31 for (int i = 1000; i-- > 0;) {
32 fWStream->writeText("HELLO SKIA!\n");
33 }
34 }
35 }
36};
37} // namespace
38
39DEF_BENCH(return new WStreamWriteTextBenchmark;)
40
Hal Canary3c36ef62018-01-02 16:25:53 -050041// Test speed of SkFloatToDecimal for typical floats that
42// might be found in a PDF document.
43struct PDFScalarBench : public Benchmark {
Hal Canaryb4a8a622018-02-21 15:49:41 -050044 PDFScalarBench(const char* n, float (*f)(SkRandom*)) : fName(n), fNextFloat(f) {}
45 const char* fName;
46 float (*fNextFloat)(SkRandom*);
Hal Canary3c36ef62018-01-02 16:25:53 -050047 bool isSuitableFor(Backend b) override {
48 return b == kNonRendering_Backend;
49 }
Hal Canaryb4a8a622018-02-21 15:49:41 -050050 const char* onGetName() override { return fName; }
Hal Canary3c36ef62018-01-02 16:25:53 -050051 void onDraw(int loops, SkCanvas*) override {
52 SkRandom random;
53 char dst[kMaximumSkFloatToDecimalLength];
54 while (loops-- > 0) {
Hal Canaryb4a8a622018-02-21 15:49:41 -050055 auto f = fNextFloat(&random);
Hal Canary3c36ef62018-01-02 16:25:53 -050056 (void)SkFloatToDecimal(f, dst);
57 }
58 }
59};
60
Hal Canaryb4a8a622018-02-21 15:49:41 -050061float next_common(SkRandom* random) {
62 return random->nextRangeF(-500.0f, 1500.0f);
63}
64float next_any(SkRandom* random) {
65 union { uint32_t u; float f; };
66 u = random->nextU();
67 static_assert(sizeof(float) == sizeof(uint32_t), "");
68 return f;
69}
70
71DEF_BENCH(return new PDFScalarBench("PDFScalar_common", next_common);)
72DEF_BENCH(return new PDFScalarBench("PDFScalar_random", next_any);)
Hal Canary3c36ef62018-01-02 16:25:53 -050073
Hal Canary43fb7a02016-12-30 13:09:03 -050074#ifdef SK_SUPPORT_PDF
75
76#include "SkPDFBitmap.h"
Hal Canary23564b92018-09-07 14:33:14 -040077#include "SkPDFDocumentPriv.h"
Hal Canary43fb7a02016-12-30 13:09:03 -050078#include "SkPDFShader.h"
Hal Canary23564b92018-09-07 14:33:14 -040079#include "SkPDFUtils.h"
Hal Canary43fb7a02016-12-30 13:09:03 -050080
81namespace {
halcanarya50151d2016-03-25 11:57:49 -070082static void test_pdf_object_serialization(const sk_sp<SkPDFObject> object) {
halcanary1abea462016-02-24 09:25:58 -080083 // SkDebugWStream wStream;
Mike Reed2a65cc02017-03-22 10:01:53 -040084 SkNullWStream wStream;
halcanary1abea462016-02-24 09:25:58 -080085 SkPDFObjNumMap objNumMap;
halcanary530032a2016-08-18 14:22:52 -070086 objNumMap.addObjectRecursively(object.get());
Hal Canary9e41c212018-09-03 12:00:23 -040087 for (size_t i = 0; i < objNumMap.objects().size(); ++i) {
halcanarybae235e2016-03-21 10:05:23 -070088 SkPDFObject* object = objNumMap.objects()[i].get();
Cary Clark60ebf142018-09-06 12:22:33 +000089 wStream.writeDecAsText(i + 1);
halcanary1abea462016-02-24 09:25:58 -080090 wStream.writeText(" 0 obj\n");
halcanary530032a2016-08-18 14:22:52 -070091 object->emitObject(&wStream, objNumMap);
halcanary1abea462016-02-24 09:25:58 -080092 wStream.writeText("\nendobj\n");
93 }
94}
95
96class PDFImageBench : public Benchmark {
97public:
98 PDFImageBench() {}
Brian Salomond3b65972017-03-22 12:05:03 -040099 ~PDFImageBench() override {}
halcanary1abea462016-02-24 09:25:58 -0800100
101protected:
102 const char* onGetName() override { return "PDFImage"; }
103 bool isSuitableFor(Backend backend) override {
104 return backend == kNonRendering_Backend;
105 }
106 void onDelayedSetup() override {
Hal Canaryc465d132017-12-08 10:21:31 -0500107 sk_sp<SkImage> img(GetResourceAsImage("images/color_wheel.png"));
halcanary1abea462016-02-24 09:25:58 -0800108 if (img) {
109 // force decoding, throw away reference to encoded data.
110 SkAutoPixmapStorage pixmap;
111 pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions()));
112 if (img->readPixels(pixmap, 0, 0)) {
reed9ce9d672016-03-17 10:51:11 -0700113 fImage = SkImage::MakeRasterCopy(pixmap);
halcanary1abea462016-02-24 09:25:58 -0800114 }
115 }
116 }
117 void onDraw(int loops, SkCanvas*) override {
118 if (!fImage) {
119 return;
120 }
121 while (loops-- > 0) {
Mike Reed2e3f2e92017-12-15 20:43:03 +0000122 auto object = SkPDFCreateBitmapObject(fImage);
halcanary1e440512016-02-24 15:17:19 -0800123 SkASSERT(object);
124 if (!object) {
125 return;
126 }
127 test_pdf_object_serialization(object);
halcanary1abea462016-02-24 09:25:58 -0800128 }
129 }
130
131private:
reed9ce9d672016-03-17 10:51:11 -0700132 sk_sp<SkImage> fImage;
halcanary1abea462016-02-24 09:25:58 -0800133};
134
135class PDFJpegImageBench : public Benchmark {
136public:
137 PDFJpegImageBench() {}
Brian Salomond3b65972017-03-22 12:05:03 -0400138 ~PDFJpegImageBench() override {}
halcanary1abea462016-02-24 09:25:58 -0800139
140protected:
141 const char* onGetName() override { return "PDFJpegImage"; }
142 bool isSuitableFor(Backend backend) override {
143 return backend == kNonRendering_Backend;
144 }
145 void onDelayedSetup() override {
Hal Canaryc465d132017-12-08 10:21:31 -0500146 sk_sp<SkImage> img(GetResourceAsImage("images/mandrill_512_q075.jpg"));
halcanary1abea462016-02-24 09:25:58 -0800147 if (!img) { return; }
Mike Reed6409f842017-07-11 16:03:13 -0400148 sk_sp<SkData> encoded = img->refEncodedData();
halcanary1abea462016-02-24 09:25:58 -0800149 SkASSERT(encoded);
150 if (!encoded) { return; }
reed9ce9d672016-03-17 10:51:11 -0700151 fImage = img;
halcanary1abea462016-02-24 09:25:58 -0800152 }
153 void onDraw(int loops, SkCanvas*) override {
154 if (!fImage) {
155 SkDEBUGFAIL("");
156 return;
157 }
158 while (loops-- > 0) {
Mike Reed2e3f2e92017-12-15 20:43:03 +0000159 auto object = SkPDFCreateBitmapObject(fImage);
halcanary1e440512016-02-24 15:17:19 -0800160 SkASSERT(object);
161 if (!object) {
162 return;
163 }
164 test_pdf_object_serialization(object);
halcanary1abea462016-02-24 09:25:58 -0800165 }
166 }
167
168private:
reed9ce9d672016-03-17 10:51:11 -0700169 sk_sp<SkImage> fImage;
halcanary1abea462016-02-24 09:25:58 -0800170};
171
halcanary1e440512016-02-24 15:17:19 -0800172/** Test calling DEFLATE on a 78k PDF command stream. Used for measuring
173 alternate zlib settings, usage, and library versions. */
174class PDFCompressionBench : public Benchmark {
175public:
176 PDFCompressionBench() {}
Brian Salomond3b65972017-03-22 12:05:03 -0400177 ~PDFCompressionBench() override {}
halcanary1e440512016-02-24 15:17:19 -0800178
179protected:
180 const char* onGetName() override { return "PDFCompression"; }
181 bool isSuitableFor(Backend backend) override {
182 return backend == kNonRendering_Backend;
183 }
184 void onDelayedSetup() override {
Mike Reed71f867c2017-07-23 13:14:10 -0400185 fAsset = GetResourceAsStream("pdf_command_stream.txt");
halcanary1e440512016-02-24 15:17:19 -0800186 }
187 void onDraw(int loops, SkCanvas*) override {
188 SkASSERT(fAsset);
189 if (!fAsset) { return; }
190 while (loops-- > 0) {
halcanaryfa251062016-07-29 10:13:18 -0700191 sk_sp<SkPDFObject> object =
192 sk_make_sp<SkPDFSharedStream>(
193 std::unique_ptr<SkStreamAsset>(fAsset->duplicate()));
halcanary1e440512016-02-24 15:17:19 -0800194 test_pdf_object_serialization(object);
195 }
196 }
197
198private:
Ben Wagner145dbcd2016-11-03 14:40:50 -0400199 std::unique_ptr<SkStreamAsset> fAsset;
halcanary1e440512016-02-24 15:17:19 -0800200};
201
halcanaryeb92cb32016-07-15 13:41:27 -0700202struct PDFColorComponentBench : public Benchmark {
203 bool isSuitableFor(Backend b) override {
204 return b == kNonRendering_Backend;
205 }
206 const char* onGetName() override { return "PDFColorComponent"; }
207 void onDraw(int loops, SkCanvas*) override {
208 char dst[5];
209 while (loops-- > 0) {
210 for (int i = 0; i < 256; ++i) {
211 (void)SkPDFUtils::ColorToDecimal(SkToU8(i), dst);
212 }
213 }
214 }
215};
216
halcanaryd11c7262016-03-25 05:52:57 -0700217struct PDFShaderBench : public Benchmark {
218 sk_sp<SkShader> fShader;
219 const char* onGetName() final { return "PDFShader"; }
220 bool isSuitableFor(Backend b) final { return b == kNonRendering_Backend; }
221 void onDelayedSetup() final {
222 const SkPoint pts[2] = {{0.0f, 0.0f}, {100.0f, 100.0f}};
223 const SkColor colors[] = {
224 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
225 SK_ColorWHITE, SK_ColorBLACK,
226 };
227 fShader = SkGradientShader::MakeLinear(
228 pts, colors, nullptr, SK_ARRAY_COUNT(colors),
229 SkShader::kClamp_TileMode);
230 }
231 void onDraw(int loops, SkCanvas*) final {
232 SkASSERT(fShader);
233 while (loops-- > 0) {
Mike Reed2a65cc02017-03-22 10:01:53 -0400234 SkNullWStream nullStream;
Hal Canary23564b92018-09-07 14:33:14 -0400235 SkPDFDocument doc(&nullStream, SkPDF::Metadata());
Hal Canary7e872ca2017-07-19 15:51:18 -0400236 sk_sp<SkPDFObject> shader = SkPDFMakeShader(&doc, fShader.get(), SkMatrix::I(),
237 {0, 0, 400, 400}, SK_ColorBLACK);
halcanaryd11c7262016-03-25 05:52:57 -0700238 }
239 }
240};
241
halcanaryee41b752016-06-23 14:08:11 -0700242struct WritePDFTextBenchmark : public Benchmark {
243 std::unique_ptr<SkWStream> fWStream;
Mike Reed2a65cc02017-03-22 10:01:53 -0400244 WritePDFTextBenchmark() : fWStream(new SkNullWStream) {}
halcanaryee41b752016-06-23 14:08:11 -0700245 const char* onGetName() override { return "WritePDFText"; }
246 bool isSuitableFor(Backend backend) override {
247 return backend == kNonRendering_Backend;
248 }
249 void onDraw(int loops, SkCanvas*) override {
250 static const char kHello[] = "HELLO SKIA!\n";
251 static const char kBinary[] = "\001\002\003\004\005\006";
252 while (loops-- > 0) {
253 for (int i = 1000; i-- > 0;) {
Hal Canarye650b852018-09-12 09:12:36 -0400254 SkPDFWriteString(fWStream.get(), kHello, strlen(kHello));
255 SkPDFWriteString(fWStream.get(), kBinary, strlen(kBinary));
halcanaryee41b752016-06-23 14:08:11 -0700256 }
257 }
258 }
259};
260
halcanary1abea462016-02-24 09:25:58 -0800261} // namespace
262DEF_BENCH(return new PDFImageBench;)
263DEF_BENCH(return new PDFJpegImageBench;)
halcanary1e440512016-02-24 15:17:19 -0800264DEF_BENCH(return new PDFCompressionBench;)
halcanaryeb92cb32016-07-15 13:41:27 -0700265DEF_BENCH(return new PDFColorComponentBench;)
halcanaryd11c7262016-03-25 05:52:57 -0700266DEF_BENCH(return new PDFShaderBench;)
halcanaryee41b752016-06-23 14:08:11 -0700267DEF_BENCH(return new WritePDFTextBenchmark;)
Hal Canary43fb7a02016-12-30 13:09:03 -0500268
269#endif
270