blob: e0d4934bcee330b53968c6aa20952aa8d97fb5bd [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"
halcanaryd11c7262016-03-25 05:52:57 -070013#include "SkGradientShader.h"
halcanary1e440512016-02-24 15:17:19 -080014#include "SkImage.h"
halcanary1e440512016-02-24 15:17:19 -080015#include "SkPixmap.h"
halcanarycf430132016-03-09 10:49:23 -080016#include "SkRandom.h"
halcanarycbc060a2016-04-11 19:41:48 -070017#include "SkStream.h"
halcanary1abea462016-02-24 09:25:58 -080018
19namespace {
20struct NullWStream : public SkWStream {
21 NullWStream() : fN(0) {}
22 bool write(const void*, size_t n) override { fN += n; return true; }
23 size_t bytesWritten() const override { return fN; }
24 size_t fN;
25};
26
Hal Canary43fb7a02016-12-30 13:09:03 -050027struct WStreamWriteTextBenchmark : public Benchmark {
28 std::unique_ptr<SkWStream> fWStream;
29 WStreamWriteTextBenchmark() : fWStream(new NullWStream) {}
30 const char* onGetName() override { return "WStreamWriteText"; }
31 bool isSuitableFor(Backend backend) override {
32 return backend == kNonRendering_Backend;
33 }
34 void onDraw(int loops, SkCanvas*) override {
35 while (loops-- > 0) {
36 for (int i = 1000; i-- > 0;) {
37 fWStream->writeText("HELLO SKIA!\n");
38 }
39 }
40 }
41};
42} // namespace
43
44DEF_BENCH(return new WStreamWriteTextBenchmark;)
45
46#ifdef SK_SUPPORT_PDF
47
48#include "SkPDFBitmap.h"
49#include "SkPDFDocument.h"
50#include "SkPDFShader.h"
51#include "SkPDFUtils.h"
52
53namespace {
halcanarya50151d2016-03-25 11:57:49 -070054static void test_pdf_object_serialization(const sk_sp<SkPDFObject> object) {
halcanary1abea462016-02-24 09:25:58 -080055 // SkDebugWStream wStream;
56 NullWStream wStream;
halcanary1abea462016-02-24 09:25:58 -080057 SkPDFObjNumMap objNumMap;
halcanary530032a2016-08-18 14:22:52 -070058 objNumMap.addObjectRecursively(object.get());
halcanary1abea462016-02-24 09:25:58 -080059 for (int i = 0; i < objNumMap.objects().count(); ++i) {
halcanarybae235e2016-03-21 10:05:23 -070060 SkPDFObject* object = objNumMap.objects()[i].get();
halcanary1abea462016-02-24 09:25:58 -080061 wStream.writeDecAsText(i + 1);
62 wStream.writeText(" 0 obj\n");
halcanary530032a2016-08-18 14:22:52 -070063 object->emitObject(&wStream, objNumMap);
halcanary1abea462016-02-24 09:25:58 -080064 wStream.writeText("\nendobj\n");
65 }
66}
67
68class PDFImageBench : public Benchmark {
69public:
70 PDFImageBench() {}
71 virtual ~PDFImageBench() {}
72
73protected:
74 const char* onGetName() override { return "PDFImage"; }
75 bool isSuitableFor(Backend backend) override {
76 return backend == kNonRendering_Backend;
77 }
78 void onDelayedSetup() override {
reed9ce9d672016-03-17 10:51:11 -070079 sk_sp<SkImage> img(GetResourceAsImage("color_wheel.png"));
halcanary1abea462016-02-24 09:25:58 -080080 if (img) {
81 // force decoding, throw away reference to encoded data.
82 SkAutoPixmapStorage pixmap;
83 pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions()));
84 if (img->readPixels(pixmap, 0, 0)) {
reed9ce9d672016-03-17 10:51:11 -070085 fImage = SkImage::MakeRasterCopy(pixmap);
halcanary1abea462016-02-24 09:25:58 -080086 }
87 }
88 }
89 void onDraw(int loops, SkCanvas*) override {
90 if (!fImage) {
91 return;
92 }
93 while (loops-- > 0) {
halcanarya50151d2016-03-25 11:57:49 -070094 auto object = SkPDFCreateBitmapObject(fImage, nullptr);
halcanary1e440512016-02-24 15:17:19 -080095 SkASSERT(object);
96 if (!object) {
97 return;
98 }
99 test_pdf_object_serialization(object);
halcanary1abea462016-02-24 09:25:58 -0800100 }
101 }
102
103private:
reed9ce9d672016-03-17 10:51:11 -0700104 sk_sp<SkImage> fImage;
halcanary1abea462016-02-24 09:25:58 -0800105};
106
107class PDFJpegImageBench : public Benchmark {
108public:
109 PDFJpegImageBench() {}
110 virtual ~PDFJpegImageBench() {}
111
112protected:
113 const char* onGetName() override { return "PDFJpegImage"; }
114 bool isSuitableFor(Backend backend) override {
115 return backend == kNonRendering_Backend;
116 }
117 void onDelayedSetup() override {
reed9ce9d672016-03-17 10:51:11 -0700118 sk_sp<SkImage> img(GetResourceAsImage("mandrill_512_q075.jpg"));
halcanary1abea462016-02-24 09:25:58 -0800119 if (!img) { return; }
halcanarya50151d2016-03-25 11:57:49 -0700120 sk_sp<SkData> encoded(img->refEncoded());
halcanary1abea462016-02-24 09:25:58 -0800121 SkASSERT(encoded);
122 if (!encoded) { return; }
reed9ce9d672016-03-17 10:51:11 -0700123 fImage = img;
halcanary1abea462016-02-24 09:25:58 -0800124 }
125 void onDraw(int loops, SkCanvas*) override {
126 if (!fImage) {
127 SkDEBUGFAIL("");
128 return;
129 }
130 while (loops-- > 0) {
halcanarya50151d2016-03-25 11:57:49 -0700131 auto object = SkPDFCreateBitmapObject(fImage, nullptr);
halcanary1e440512016-02-24 15:17:19 -0800132 SkASSERT(object);
133 if (!object) {
134 return;
135 }
136 test_pdf_object_serialization(object);
halcanary1abea462016-02-24 09:25:58 -0800137 }
138 }
139
140private:
reed9ce9d672016-03-17 10:51:11 -0700141 sk_sp<SkImage> fImage;
halcanary1abea462016-02-24 09:25:58 -0800142};
143
halcanary1e440512016-02-24 15:17:19 -0800144/** Test calling DEFLATE on a 78k PDF command stream. Used for measuring
145 alternate zlib settings, usage, and library versions. */
146class PDFCompressionBench : public Benchmark {
147public:
148 PDFCompressionBench() {}
149 virtual ~PDFCompressionBench() {}
150
151protected:
152 const char* onGetName() override { return "PDFCompression"; }
153 bool isSuitableFor(Backend backend) override {
154 return backend == kNonRendering_Backend;
155 }
156 void onDelayedSetup() override {
157 fAsset.reset(GetResourceAsStream("pdf_command_stream.txt"));
158 }
159 void onDraw(int loops, SkCanvas*) override {
160 SkASSERT(fAsset);
161 if (!fAsset) { return; }
162 while (loops-- > 0) {
halcanaryfa251062016-07-29 10:13:18 -0700163 sk_sp<SkPDFObject> object =
164 sk_make_sp<SkPDFSharedStream>(
165 std::unique_ptr<SkStreamAsset>(fAsset->duplicate()));
halcanary1e440512016-02-24 15:17:19 -0800166 test_pdf_object_serialization(object);
167 }
168 }
169
170private:
Ben Wagner145dbcd2016-11-03 14:40:50 -0400171 std::unique_ptr<SkStreamAsset> fAsset;
halcanary1e440512016-02-24 15:17:19 -0800172};
173
halcanarycf430132016-03-09 10:49:23 -0800174// Test speed of SkPDFUtils::FloatToDecimal for typical floats that
175// might be found in a PDF document.
176struct PDFScalarBench : public Benchmark {
177 bool isSuitableFor(Backend b) override {
178 return b == kNonRendering_Backend;
179 }
180 const char* onGetName() override { return "PDFScalar"; }
181 void onDraw(int loops, SkCanvas*) override {
182 SkRandom random;
183 char dst[SkPDFUtils::kMaximumFloatDecimalLength];
184 while (loops-- > 0) {
185 auto f = random.nextRangeF(-500.0f, 1500.0f);
186 (void)SkPDFUtils::FloatToDecimal(f, dst);
187 }
188 }
189};
190
halcanaryeb92cb32016-07-15 13:41:27 -0700191struct PDFColorComponentBench : public Benchmark {
192 bool isSuitableFor(Backend b) override {
193 return b == kNonRendering_Backend;
194 }
195 const char* onGetName() override { return "PDFColorComponent"; }
196 void onDraw(int loops, SkCanvas*) override {
197 char dst[5];
198 while (loops-- > 0) {
199 for (int i = 0; i < 256; ++i) {
200 (void)SkPDFUtils::ColorToDecimal(SkToU8(i), dst);
201 }
202 }
203 }
204};
205
halcanaryd11c7262016-03-25 05:52:57 -0700206struct PDFShaderBench : public Benchmark {
207 sk_sp<SkShader> fShader;
208 const char* onGetName() final { return "PDFShader"; }
209 bool isSuitableFor(Backend b) final { return b == kNonRendering_Backend; }
210 void onDelayedSetup() final {
211 const SkPoint pts[2] = {{0.0f, 0.0f}, {100.0f, 100.0f}};
212 const SkColor colors[] = {
213 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
214 SK_ColorWHITE, SK_ColorBLACK,
215 };
216 fShader = SkGradientShader::MakeLinear(
217 pts, colors, nullptr, SK_ARRAY_COUNT(colors),
218 SkShader::kClamp_TileMode);
219 }
220 void onDraw(int loops, SkCanvas*) final {
221 SkASSERT(fShader);
222 while (loops-- > 0) {
223 NullWStream nullStream;
halcanary4b656662016-04-27 07:45:18 -0700224 SkPDFDocument doc(&nullStream, nullptr, 72,
225 SkDocument::PDFMetadata(), nullptr, false);
halcanaryd11c7262016-03-25 05:52:57 -0700226 sk_sp<SkPDFObject> shader(
227 SkPDFShader::GetPDFShader(
reedfe630452016-03-25 09:08:00 -0700228 &doc, 72, fShader.get(), SkMatrix::I(),
halcanaryd11c7262016-03-25 05:52:57 -0700229 SkIRect::MakeWH(400,400), 72));
230 }
231 }
232};
233
halcanaryee41b752016-06-23 14:08:11 -0700234struct WritePDFTextBenchmark : public Benchmark {
235 std::unique_ptr<SkWStream> fWStream;
236 WritePDFTextBenchmark() : fWStream(new NullWStream) {}
237 const char* onGetName() override { return "WritePDFText"; }
238 bool isSuitableFor(Backend backend) override {
239 return backend == kNonRendering_Backend;
240 }
241 void onDraw(int loops, SkCanvas*) override {
242 static const char kHello[] = "HELLO SKIA!\n";
243 static const char kBinary[] = "\001\002\003\004\005\006";
244 while (loops-- > 0) {
245 for (int i = 1000; i-- > 0;) {
246 SkPDFUtils::WriteString(fWStream.get(), kHello, strlen(kHello));
247 SkPDFUtils::WriteString(fWStream.get(), kBinary, strlen(kBinary));
248 }
249 }
250 }
251};
252
halcanary1abea462016-02-24 09:25:58 -0800253} // namespace
254DEF_BENCH(return new PDFImageBench;)
255DEF_BENCH(return new PDFJpegImageBench;)
halcanary1e440512016-02-24 15:17:19 -0800256DEF_BENCH(return new PDFCompressionBench;)
halcanarycf430132016-03-09 10:49:23 -0800257DEF_BENCH(return new PDFScalarBench;)
halcanaryeb92cb32016-07-15 13:41:27 -0700258DEF_BENCH(return new PDFColorComponentBench;)
halcanaryd11c7262016-03-25 05:52:57 -0700259DEF_BENCH(return new PDFShaderBench;)
halcanaryee41b752016-06-23 14:08:11 -0700260DEF_BENCH(return new WritePDFTextBenchmark;)
Hal Canary43fb7a02016-12-30 13:09:03 -0500261
262#endif
263