1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "Benchmark.h"
9#include "SkBitmap.h"
10#include "SkCanvas.h"
11#include "SkColorPriv.h"
12#include "SkPaint.h"
13#include "SkShader.h"
14#include "SkString.h"
15#include "sk_tool_utils.h"
16
17static void draw_into_bitmap(const SkBitmap& bm) {
18    const int w = bm.width();
19    const int h = bm.height();
20
21    SkCanvas canvas(bm);
22    SkPaint p;
23    p.setAntiAlias(true);
24    p.setColor(SK_ColorRED);
25    canvas.drawCircle(SkIntToScalar(w)/2, SkIntToScalar(h)/2,
26                      SkIntToScalar(SkMin32(w, h))*3/8, p);
27
28    SkRect r;
29    r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
30    p.setStyle(SkPaint::kStroke_Style);
31    p.setStrokeWidth(SkIntToScalar(4));
32    p.setColor(SK_ColorBLUE);
33    canvas.drawRect(r, p);
34}
35
36static int conv_6_to_byte(int x) {
37    return x * 0xFF / 5;
38}
39
40static int conv_byte_to_6(int x) {
41    return x * 5 / 255;
42}
43
44static uint8_t compute_666_index(SkPMColor c) {
45    int r = SkGetPackedR32(c);
46    int g = SkGetPackedG32(c);
47    int b = SkGetPackedB32(c);
48
49    return conv_byte_to_6(r) * 36 + conv_byte_to_6(g) * 6 + conv_byte_to_6(b);
50}
51
52static void convert_to_index666(const SkBitmap& src, SkBitmap* dst) {
53    SkPMColor storage[216];
54    SkPMColor* colors = storage;
55    // rrr ggg bbb
56    for (int r = 0; r < 6; r++) {
57        int rr = conv_6_to_byte(r);
58        for (int g = 0; g < 6; g++) {
59            int gg = conv_6_to_byte(g);
60            for (int b = 0; b < 6; b++) {
61                int bb = conv_6_to_byte(b);
62                *colors++ = SkPreMultiplyARGB(0xFF, rr, gg, bb);
63            }
64        }
65    }
66    SkColorTable* ctable = new SkColorTable(storage, 216, kOpaque_SkAlphaType);
67    dst->allocPixels(SkImageInfo::Make(src.width(), src.height(),
68                                       kIndex_8_SkColorType, kOpaque_SkAlphaType),
69                     NULL, ctable);
70    ctable->unref();
71
72    SkAutoLockPixels alps(src);
73    SkAutoLockPixels alpd(*dst);
74
75    for (int y = 0; y < src.height(); y++) {
76        const SkPMColor* srcP = src.getAddr32(0, y);
77        uint8_t* dstP = dst->getAddr8(0, y);
78        for (int x = src.width() - 1; x >= 0; --x) {
79            *dstP++ = compute_666_index(*srcP++);
80        }
81    }
82}
83
84class RepeatTileBench : public Benchmark {
85    const SkColorType   fColorType;
86    const SkAlphaType   fAlphaType;
87    SkPaint             fPaint;
88    SkString            fName;
89    SkBitmap            fBitmap;
90public:
91    RepeatTileBench(SkColorType ct, SkAlphaType at = kPremul_SkAlphaType)
92        : fColorType(ct), fAlphaType(at)
93    {
94        const int w = 50;
95        const int h = 50;
96
97        if (kIndex_8_SkColorType == ct) {
98            fBitmap.setInfo(SkImageInfo::MakeN32(w, h, at));
99        } else {
100            fBitmap.setInfo(SkImageInfo::Make(w, h, ct, at));
101        }
102        fName.printf("repeatTile_%s_%c",
103                     sk_tool_utils::colortype_name(ct), kOpaque_SkAlphaType == at ? 'X' : 'A');
104    }
105
106protected:
107    virtual const char* onGetName() SK_OVERRIDE {
108        return fName.c_str();
109    }
110
111    virtual void onPreDraw() SK_OVERRIDE {
112        fBitmap.allocPixels();
113        fBitmap.eraseColor(kOpaque_SkAlphaType == fAlphaType ? SK_ColorWHITE : 0);
114
115        draw_into_bitmap(fBitmap);
116
117        if (kIndex_8_SkColorType == fColorType) {
118            SkBitmap tmp;
119            convert_to_index666(fBitmap, &tmp);
120            fBitmap = tmp;
121        }
122
123        SkShader* s = SkShader::CreateBitmapShader(fBitmap,
124                                                   SkShader::kRepeat_TileMode,
125                                                   SkShader::kRepeat_TileMode);
126        fPaint.setShader(s)->unref();
127    }
128
129
130    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
131        SkPaint paint(fPaint);
132        this->setupPaint(&paint);
133
134        for (int i = 0; i < loops; i++) {
135            canvas->drawPaint(paint);
136        }
137    }
138
139private:
140    typedef Benchmark INHERITED;
141};
142
143DEF_BENCH(return new RepeatTileBench(kN32_SkColorType, kOpaque_SkAlphaType))
144DEF_BENCH(return new RepeatTileBench(kN32_SkColorType, kPremul_SkAlphaType))
145DEF_BENCH(return new RepeatTileBench(kRGB_565_SkColorType, kOpaque_SkAlphaType))
146DEF_BENCH(return new RepeatTileBench(kIndex_8_SkColorType, kPremul_SkAlphaType))
147