• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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