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