Home | History | Annotate | Download | only in bench
      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;
     23     WStreamWriteTextBenchmark() : fWStream(new SkNullWStream) {}
     24     const char* onGetName() override { return "WStreamWriteText"; }
     25     bool isSuitableFor(Backend backend) override {
     26         return backend == kNonRendering_Backend;
     27     }
     28     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 {
     43     bool isSuitableFor(Backend b) override {
     44         return b == kNonRendering_Backend;
     45     }
     46     const char* onGetName() override { return "PDFScalar"; }
     47     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 {
     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:
     82     PDFImageBench() {}
     83     ~PDFImageBench() override {}
     84 
     85 protected:
     86     const char* onGetName() override { return "PDFImage"; }
     87     bool isSuitableFor(Backend backend) override {
     88         return backend == kNonRendering_Backend;
     89     }
     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     }
    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:
    121     PDFJpegImageBench() {}
    122     ~PDFJpegImageBench() override {}
    123 
    124 protected:
    125     const char* onGetName() override { return "PDFJpegImage"; }
    126     bool isSuitableFor(Backend backend) override {
    127         return backend == kNonRendering_Backend;
    128     }
    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     }
    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:
    160     PDFCompressionBench() {}
    161     ~PDFCompressionBench() override {}
    162 
    163 protected:
    164     const char* onGetName() override { return "PDFCompression"; }
    165     bool isSuitableFor(Backend backend) override {
    166         return backend == kNonRendering_Backend;
    167     }
    168     void onDelayedSetup() override {
    169         fAsset = GetResourceAsStream("pdf_command_stream.txt");
    170     }
    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 {
    187     bool isSuitableFor(Backend b) override {
    188         return b == kNonRendering_Backend;
    189     }
    190     const char* onGetName() override { return "PDFColorComponent"; }
    191     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;
    203     const char* onGetName() final { return "PDFShader"; }
    204     bool isSuitableFor(Backend b) final { return b == kNonRendering_Backend; }
    205     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     }
    215     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;
    228     WritePDFTextBenchmark() : fWStream(new SkNullWStream) {}
    229     const char* onGetName() override { return "WritePDFText"; }
    230     bool isSuitableFor(Backend backend) override {
    231         return backend == kNonRendering_Backend;
    232     }
    233     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