1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2016 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Benchmark.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Resources.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBitmap.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkJpegEncoder.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPngEncoder.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkWebpEncoder.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStream.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass EncodeBench : public Benchmark {
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    using Encoder = bool (*)(SkWStream*, const SkPixmap&);
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    EncodeBench(const char* filename, Encoder encoder, const char* encoderName)
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : fSourceFilename(filename)
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fEncoder(encoder)
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fName(SkStringPrintf("Encode_%s_%s", filename, encoderName)) {}
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* onGetName() override { return fName.c_str(); }
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onPreDraw(SkCanvas*) override {
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkAssertResult(GetResourceAsBitmap(fSourceFilename, &fBitmap));
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onDraw(int loops, SkCanvas*) override {
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while (loops-- > 0) {
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkPixmap pixmap;
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkAssertResult(fBitmap.peekPixels(&pixmap));
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkNullWStream dst;
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkAssertResult(fEncoder(&dst, pixmap));
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT(dst.bytesWritten() > 0);
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* fSourceFilename;
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Encoder     fEncoder;
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString    fName;
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkBitmap    fBitmap;
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool encode_jpeg(SkWStream* dst, const SkPixmap& src) {
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkJpegEncoder::Options opts;
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    opts.fQuality = 90;
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkJpegEncoder::Encode(dst, src, opts);
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool encode_webp_lossy(SkWStream* dst, const SkPixmap& src) {
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkWebpEncoder::Options opts;
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    opts.fCompression = SkWebpEncoder::Compression::kLossy;
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    opts.fQuality = 90;
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    opts.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore;
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkWebpEncoder::Encode(dst, src, opts);
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool encode_webp_lossless(SkWStream* dst, const SkPixmap& src) {
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkWebpEncoder::Options opts;
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    opts.fCompression = SkWebpEncoder::Compression::kLossless;
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    opts.fQuality = 90;
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    opts.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore;
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkWebpEncoder::Encode(dst, src, opts);
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool encode_png(SkWStream* dst,
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       const SkPixmap& src,
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       SkPngEncoder::FilterFlag filters,
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       int zlibLevel) {
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPngEncoder::Options opts;
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    opts.fFilterFlags = filters;
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    opts.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore;
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    opts.fZLibLevel = zlibLevel;
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkPngEncoder::Encode(dst, src, opts);
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define PNG(FLAG, ZLIBLEVEL) [](SkWStream* d, const SkPixmap& s) { \
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot           return encode_png(d, s, SkPngEncoder::FilterFlag::FLAG, ZLIBLEVEL); }
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const char* srcs[2] = {"images/mandrill_512.png", "images/color_wheel.jpg"};
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// The Android Photos app uses a quality of 90 on JPEG encodes
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], &encode_jpeg, "JPEG"));
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], &encode_jpeg, "JPEG"));
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// TODO: What is the appropriate quality to use to benchmark WEBP encodes?
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], encode_webp_lossy, "WEBP"));
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], encode_webp_lossy, "WEBP"));
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], encode_webp_lossless, "WEBP_LL"));
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], encode_webp_lossless, "WEBP_LL"));
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 6), "PNG"));
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 3), "PNG_3"));
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 1), "PNG_1"));
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 6), "PNG_6s"));
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 3), "PNG_3s"));
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 1), "PNG_1s"));
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 6), "PNG_6n"));
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 3), "PNG_3n"));
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 1), "PNG_1n"));
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 6), "PNG"));
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 3), "PNG_3"));
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 1), "PNG_1"));
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 6), "PNG_6s"));
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 3), "PNG_3s"));
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 1), "PNG_1s"));
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 6), "PNG_6n"));
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 3), "PNG_3n"));
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 1), "PNG_1n"));
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef PNG
123