1 /*
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"
9
10 #include "Resources.h"
11 #include "SkAutoPixmapStorage.h"
12 #include "SkData.h"
13 #include "SkFloatToDecimal.h"
14 #include "SkGradientShader.h"
15 #include "SkImage.h"
16 #include "SkPixmap.h"
17 #include "SkRandom.h"
18 #include "SkStream.h"
19
20 namespace {
21 struct WStreamWriteTextBenchmark : public Benchmark {
22 std::unique_ptr<SkWStream> fWStream;
WStreamWriteTextBenchmark__anon9fd002d60111::WStreamWriteTextBenchmark23 WStreamWriteTextBenchmark() : fWStream(new SkNullWStream) {}
onGetName__anon9fd002d60111::WStreamWriteTextBenchmark24 const char* onGetName() override { return "WStreamWriteText"; }
isSuitableFor__anon9fd002d60111::WStreamWriteTextBenchmark25 bool isSuitableFor(Backend backend) override {
26 return backend == kNonRendering_Backend;
27 }
onDraw__anon9fd002d60111::WStreamWriteTextBenchmark28 void onDraw(int loops, SkCanvas*) override {
29 while (loops-- > 0) {
30 for (int i = 1000; i-- > 0;) {
31 fWStream->writeText("HELLO SKIA!\n");
32 }
33 }
34 }
35 };
36 } // namespace
37
38 DEF_BENCH(return new WStreamWriteTextBenchmark;)
39
40 // Test speed of SkFloatToDecimal for typical floats that
41 // might be found in a PDF document.
42 struct PDFScalarBench : public Benchmark {
isSuitableForPDFScalarBench43 bool isSuitableFor(Backend b) override {
44 return b == kNonRendering_Backend;
45 }
onGetNamePDFScalarBench46 const char* onGetName() override { return "PDFScalar"; }
onDrawPDFScalarBench47 void onDraw(int loops, SkCanvas*) override {
48 SkRandom random;
49 char dst[kMaximumSkFloatToDecimalLength];
50 while (loops-- > 0) {
51 auto f = random.nextRangeF(-500.0f, 1500.0f);
52 (void)SkFloatToDecimal(f, dst);
53 }
54 }
55 };
56
57 DEF_BENCH(return new PDFScalarBench;)
58
59 #ifdef SK_SUPPORT_PDF
60
61 #include "SkPDFBitmap.h"
62 #include "SkPDFDocument.h"
63 #include "SkPDFShader.h"
64
65 namespace {
test_pdf_object_serialization(const sk_sp<SkPDFObject> object)66 static void test_pdf_object_serialization(const sk_sp<SkPDFObject> object) {
67 // SkDebugWStream wStream;
68 SkNullWStream wStream;
69 SkPDFObjNumMap objNumMap;
70 objNumMap.addObjectRecursively(object.get());
71 for (int i = 0; i < objNumMap.objects().count(); ++i) {
72 SkPDFObject* object = objNumMap.objects()[i].get();
73 wStream.writeDecAsText(i + 1);
74 wStream.writeText(" 0 obj\n");
75 object->emitObject(&wStream, objNumMap);
76 wStream.writeText("\nendobj\n");
77 }
78 }
79
80 class PDFImageBench : public Benchmark {
81 public:
PDFImageBench()82 PDFImageBench() {}
~PDFImageBench()83 ~PDFImageBench() override {}
84
85 protected:
onGetName()86 const char* onGetName() override { return "PDFImage"; }
isSuitableFor(Backend backend)87 bool isSuitableFor(Backend backend) override {
88 return backend == kNonRendering_Backend;
89 }
onDelayedSetup()90 void onDelayedSetup() override {
91 sk_sp<SkImage> img(GetResourceAsImage("images/color_wheel.png"));
92 if (img) {
93 // force decoding, throw away reference to encoded data.
94 SkAutoPixmapStorage pixmap;
95 pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions()));
96 if (img->readPixels(pixmap, 0, 0)) {
97 fImage = SkImage::MakeRasterCopy(pixmap);
98 }
99 }
100 }
onDraw(int loops,SkCanvas *)101 void onDraw(int loops, SkCanvas*) override {
102 if (!fImage) {
103 return;
104 }
105 while (loops-- > 0) {
106 auto object = SkPDFCreateBitmapObject(fImage);
107 SkASSERT(object);
108 if (!object) {
109 return;
110 }
111 test_pdf_object_serialization(object);
112 }
113 }
114
115 private:
116 sk_sp<SkImage> fImage;
117 };
118
119 class PDFJpegImageBench : public Benchmark {
120 public:
PDFJpegImageBench()121 PDFJpegImageBench() {}
~PDFJpegImageBench()122 ~PDFJpegImageBench() override {}
123
124 protected:
onGetName()125 const char* onGetName() override { return "PDFJpegImage"; }
isSuitableFor(Backend backend)126 bool isSuitableFor(Backend backend) override {
127 return backend == kNonRendering_Backend;
128 }
onDelayedSetup()129 void onDelayedSetup() override {
130 sk_sp<SkImage> img(GetResourceAsImage("images/mandrill_512_q075.jpg"));
131 if (!img) { return; }
132 sk_sp<SkData> encoded = img->refEncodedData();
133 SkASSERT(encoded);
134 if (!encoded) { return; }
135 fImage = img;
136 }
onDraw(int loops,SkCanvas *)137 void onDraw(int loops, SkCanvas*) override {
138 if (!fImage) {
139 SkDEBUGFAIL("");
140 return;
141 }
142 while (loops-- > 0) {
143 auto object = SkPDFCreateBitmapObject(fImage);
144 SkASSERT(object);
145 if (!object) {
146 return;
147 }
148 test_pdf_object_serialization(object);
149 }
150 }
151
152 private:
153 sk_sp<SkImage> fImage;
154 };
155
156 /** Test calling DEFLATE on a 78k PDF command stream. Used for measuring
157 alternate zlib settings, usage, and library versions. */
158 class PDFCompressionBench : public Benchmark {
159 public:
PDFCompressionBench()160 PDFCompressionBench() {}
~PDFCompressionBench()161 ~PDFCompressionBench() override {}
162
163 protected:
onGetName()164 const char* onGetName() override { return "PDFCompression"; }
isSuitableFor(Backend backend)165 bool isSuitableFor(Backend backend) override {
166 return backend == kNonRendering_Backend;
167 }
onDelayedSetup()168 void onDelayedSetup() override {
169 fAsset = GetResourceAsStream("pdf_command_stream.txt");
170 }
onDraw(int loops,SkCanvas *)171 void onDraw(int loops, SkCanvas*) override {
172 SkASSERT(fAsset);
173 if (!fAsset) { return; }
174 while (loops-- > 0) {
175 sk_sp<SkPDFObject> object =
176 sk_make_sp<SkPDFSharedStream>(
177 std::unique_ptr<SkStreamAsset>(fAsset->duplicate()));
178 test_pdf_object_serialization(object);
179 }
180 }
181
182 private:
183 std::unique_ptr<SkStreamAsset> fAsset;
184 };
185
186 struct PDFColorComponentBench : public Benchmark {
isSuitableFor__anon9fd002d60211::PDFColorComponentBench187 bool isSuitableFor(Backend b) override {
188 return b == kNonRendering_Backend;
189 }
onGetName__anon9fd002d60211::PDFColorComponentBench190 const char* onGetName() override { return "PDFColorComponent"; }
onDraw__anon9fd002d60211::PDFColorComponentBench191 void onDraw(int loops, SkCanvas*) override {
192 char dst[5];
193 while (loops-- > 0) {
194 for (int i = 0; i < 256; ++i) {
195 (void)SkPDFUtils::ColorToDecimal(SkToU8(i), dst);
196 }
197 }
198 }
199 };
200
201 struct PDFShaderBench : public Benchmark {
202 sk_sp<SkShader> fShader;
onGetName__anon9fd002d60211::PDFShaderBench203 const char* onGetName() final { return "PDFShader"; }
isSuitableFor__anon9fd002d60211::PDFShaderBench204 bool isSuitableFor(Backend b) final { return b == kNonRendering_Backend; }
onDelayedSetup__anon9fd002d60211::PDFShaderBench205 void onDelayedSetup() final {
206 const SkPoint pts[2] = {{0.0f, 0.0f}, {100.0f, 100.0f}};
207 const SkColor colors[] = {
208 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
209 SK_ColorWHITE, SK_ColorBLACK,
210 };
211 fShader = SkGradientShader::MakeLinear(
212 pts, colors, nullptr, SK_ARRAY_COUNT(colors),
213 SkShader::kClamp_TileMode);
214 }
onDraw__anon9fd002d60211::PDFShaderBench215 void onDraw(int loops, SkCanvas*) final {
216 SkASSERT(fShader);
217 while (loops-- > 0) {
218 SkNullWStream nullStream;
219 SkPDFDocument doc(&nullStream, SkDocument::PDFMetadata());
220 sk_sp<SkPDFObject> shader = SkPDFMakeShader(&doc, fShader.get(), SkMatrix::I(),
221 {0, 0, 400, 400}, SK_ColorBLACK);
222 }
223 }
224 };
225
226 struct WritePDFTextBenchmark : public Benchmark {
227 std::unique_ptr<SkWStream> fWStream;
WritePDFTextBenchmark__anon9fd002d60211::WritePDFTextBenchmark228 WritePDFTextBenchmark() : fWStream(new SkNullWStream) {}
onGetName__anon9fd002d60211::WritePDFTextBenchmark229 const char* onGetName() override { return "WritePDFText"; }
isSuitableFor__anon9fd002d60211::WritePDFTextBenchmark230 bool isSuitableFor(Backend backend) override {
231 return backend == kNonRendering_Backend;
232 }
onDraw__anon9fd002d60211::WritePDFTextBenchmark233 void onDraw(int loops, SkCanvas*) override {
234 static const char kHello[] = "HELLO SKIA!\n";
235 static const char kBinary[] = "\001\002\003\004\005\006";
236 while (loops-- > 0) {
237 for (int i = 1000; i-- > 0;) {
238 SkPDFUtils::WriteString(fWStream.get(), kHello, strlen(kHello));
239 SkPDFUtils::WriteString(fWStream.get(), kBinary, strlen(kBinary));
240 }
241 }
242 }
243 };
244
245 } // namespace
246 DEF_BENCH(return new PDFImageBench;)
247 DEF_BENCH(return new PDFJpegImageBench;)
248 DEF_BENCH(return new PDFCompressionBench;)
249 DEF_BENCH(return new PDFColorComponentBench;)
250 DEF_BENCH(return new PDFShaderBench;)
251 DEF_BENCH(return new WritePDFTextBenchmark;)
252
253 #endif
254
255