|  |  | 
|  | /* | 
|  | * Copyright 2011 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  | #include "Benchmark.h" | 
|  | #include "SkBitmap.h" | 
|  | #include "SkCanvas.h" | 
|  | #include "SkColorPriv.h" | 
|  | #include "SkPaint.h" | 
|  | #include "SkShader.h" | 
|  | #include "SkString.h" | 
|  | #include "sk_tool_utils.h" | 
|  |  | 
|  | static void draw_into_bitmap(const SkBitmap& bm) { | 
|  | const int w = bm.width(); | 
|  | const int h = bm.height(); | 
|  |  | 
|  | SkCanvas canvas(bm); | 
|  | SkPaint p; | 
|  | p.setAntiAlias(true); | 
|  | p.setColor(SK_ColorRED); | 
|  | canvas.drawCircle(SkIntToScalar(w)/2, SkIntToScalar(h)/2, | 
|  | SkIntToScalar(SkMin32(w, h))*3/8, p); | 
|  |  | 
|  | SkRect r; | 
|  | r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h)); | 
|  | p.setStyle(SkPaint::kStroke_Style); | 
|  | p.setStrokeWidth(SkIntToScalar(4)); | 
|  | p.setColor(SK_ColorBLUE); | 
|  | canvas.drawRect(r, p); | 
|  | } | 
|  |  | 
|  | static int conv_6_to_byte(int x) { | 
|  | return x * 0xFF / 5; | 
|  | } | 
|  |  | 
|  | static int conv_byte_to_6(int x) { | 
|  | return x * 5 / 255; | 
|  | } | 
|  |  | 
|  | static uint8_t compute_666_index(SkPMColor c) { | 
|  | int r = SkGetPackedR32(c); | 
|  | int g = SkGetPackedG32(c); | 
|  | int b = SkGetPackedB32(c); | 
|  |  | 
|  | return conv_byte_to_6(r) * 36 + conv_byte_to_6(g) * 6 + conv_byte_to_6(b); | 
|  | } | 
|  |  | 
|  | static void convert_to_index666(const SkBitmap& src, SkBitmap* dst) { | 
|  | SkPMColor storage[216]; | 
|  | SkPMColor* colors = storage; | 
|  | // rrr ggg bbb | 
|  | for (int r = 0; r < 6; r++) { | 
|  | int rr = conv_6_to_byte(r); | 
|  | for (int g = 0; g < 6; g++) { | 
|  | int gg = conv_6_to_byte(g); | 
|  | for (int b = 0; b < 6; b++) { | 
|  | int bb = conv_6_to_byte(b); | 
|  | *colors++ = SkPreMultiplyARGB(0xFF, rr, gg, bb); | 
|  | } | 
|  | } | 
|  | } | 
|  | SkColorTable* ctable = new SkColorTable(storage, 216, kOpaque_SkAlphaType); | 
|  | dst->allocPixels(SkImageInfo::Make(src.width(), src.height(), | 
|  | kIndex_8_SkColorType, kOpaque_SkAlphaType), | 
|  | NULL, ctable); | 
|  | ctable->unref(); | 
|  |  | 
|  | SkAutoLockPixels alps(src); | 
|  | SkAutoLockPixels alpd(*dst); | 
|  |  | 
|  | for (int y = 0; y < src.height(); y++) { | 
|  | const SkPMColor* srcP = src.getAddr32(0, y); | 
|  | uint8_t* dstP = dst->getAddr8(0, y); | 
|  | for (int x = src.width() - 1; x >= 0; --x) { | 
|  | *dstP++ = compute_666_index(*srcP++); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | class RepeatTileBench : public Benchmark { | 
|  | const SkColorType   fColorType; | 
|  | const SkAlphaType   fAlphaType; | 
|  | SkPaint             fPaint; | 
|  | SkString            fName; | 
|  | SkBitmap            fBitmap; | 
|  | public: | 
|  | RepeatTileBench(SkColorType ct, SkAlphaType at = kPremul_SkAlphaType) | 
|  | : fColorType(ct), fAlphaType(at) | 
|  | { | 
|  | const int w = 50; | 
|  | const int h = 50; | 
|  |  | 
|  | if (kIndex_8_SkColorType == ct) { | 
|  | fBitmap.setInfo(SkImageInfo::MakeN32(w, h, at)); | 
|  | } else { | 
|  | fBitmap.setInfo(SkImageInfo::Make(w, h, ct, at)); | 
|  | } | 
|  | fName.printf("repeatTile_%s_%c", | 
|  | sk_tool_utils::colortype_name(ct), kOpaque_SkAlphaType == at ? 'X' : 'A'); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | virtual const char* onGetName() SK_OVERRIDE { | 
|  | return fName.c_str(); | 
|  | } | 
|  |  | 
|  | virtual void onPreDraw() SK_OVERRIDE { | 
|  | fBitmap.allocPixels(); | 
|  | fBitmap.eraseColor(kOpaque_SkAlphaType == fAlphaType ? SK_ColorWHITE : 0); | 
|  |  | 
|  | draw_into_bitmap(fBitmap); | 
|  |  | 
|  | if (kIndex_8_SkColorType == fColorType) { | 
|  | SkBitmap tmp; | 
|  | convert_to_index666(fBitmap, &tmp); | 
|  | fBitmap = tmp; | 
|  | } | 
|  |  | 
|  | SkShader* s = SkShader::CreateBitmapShader(fBitmap, | 
|  | SkShader::kRepeat_TileMode, | 
|  | SkShader::kRepeat_TileMode); | 
|  | fPaint.setShader(s)->unref(); | 
|  | } | 
|  |  | 
|  |  | 
|  | virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE { | 
|  | SkPaint paint(fPaint); | 
|  | this->setupPaint(&paint); | 
|  |  | 
|  | for (int i = 0; i < loops; i++) { | 
|  | canvas->drawPaint(paint); | 
|  | } | 
|  | } | 
|  |  | 
|  | private: | 
|  | typedef Benchmark INHERITED; | 
|  | }; | 
|  |  | 
|  | DEF_BENCH(return new RepeatTileBench(kN32_SkColorType, kOpaque_SkAlphaType)) | 
|  | DEF_BENCH(return new RepeatTileBench(kN32_SkColorType, kPremul_SkAlphaType)) | 
|  | DEF_BENCH(return new RepeatTileBench(kRGB_565_SkColorType, kOpaque_SkAlphaType)) | 
|  | DEF_BENCH(return new RepeatTileBench(kIndex_8_SkColorType, kPremul_SkAlphaType)) |