|  | 
 | /* | 
 |  * 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 "SkBenchmark.h" | 
 | #include "SkCanvas.h" | 
 | #include "SkPaint.h" | 
 | #include "SkRandom.h" | 
 | #include "SkString.h" | 
 | #include "SkShader.h" | 
 |  | 
 | class RectBench : public SkBenchmark { | 
 | public: | 
 |     int fShift, fStroke; | 
 |     enum { | 
 |         W = 640, | 
 |         H = 480, | 
 |         N = SkBENCHLOOP(300) | 
 |     }; | 
 |     SkRect  fRects[N]; | 
 |     SkColor fColors[N]; | 
 |  | 
 |     RectBench(void* param, int shift, int stroke = 0) | 
 |         : INHERITED(param) | 
 |         , fShift(shift) | 
 |         , fStroke(stroke) { | 
 |         SkRandom rand; | 
 |         const SkScalar offset = SK_Scalar1/3; | 
 |         for (int i = 0; i < N; i++) { | 
 |             int x = rand.nextU() % W; | 
 |             int y = rand.nextU() % H; | 
 |             int w = rand.nextU() % W; | 
 |             int h = rand.nextU() % H; | 
 |             w >>= shift; | 
 |             h >>= shift; | 
 |             x -= w/2; | 
 |             y -= h/2; | 
 |             fRects[i].set(SkIntToScalar(x), SkIntToScalar(y), | 
 |                           SkIntToScalar(x+w), SkIntToScalar(y+h)); | 
 |             fRects[i].offset(offset, offset); | 
 |             fColors[i] = rand.nextU() | 0xFF808080; | 
 |         } | 
 |     } | 
 |  | 
 |     SkString fName; | 
 |     const char* computeName(const char root[]) { | 
 |         fName.printf("%s_%d", root, fShift); | 
 |         if (fStroke > 0) { | 
 |             fName.appendf("_stroke_%d", fStroke); | 
 |         } | 
 |         return fName.c_str(); | 
 |     } | 
 |  | 
 | protected: | 
 |     virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) { | 
 |         c->drawRect(r, p); | 
 |     } | 
 |  | 
 |     virtual const char* onGetName() { return computeName("rects"); } | 
 |     virtual void onDraw(SkCanvas* canvas) { | 
 |         SkPaint paint; | 
 |         if (fStroke > 0) { | 
 |             paint.setStyle(SkPaint::kStroke_Style); | 
 |             paint.setStrokeWidth(SkIntToScalar(fStroke)); | 
 |         } | 
 |         for (int i = 0; i < N; i++) { | 
 |             paint.setColor(fColors[i]); | 
 |             this->setupPaint(&paint); | 
 |             this->drawThisRect(canvas, fRects[i], paint); | 
 |         } | 
 |     } | 
 | private: | 
 |     typedef SkBenchmark INHERITED; | 
 | }; | 
 |  | 
 | class SrcModeRectBench : public RectBench { | 
 | public: | 
 |     SrcModeRectBench(void* param) : INHERITED(param, 1, 0) { | 
 |         fMode = SkXfermode::Create(SkXfermode::kSrc_Mode); | 
 |     } | 
 |  | 
 |     virtual ~SrcModeRectBench() { | 
 |         SkSafeUnref(fMode); | 
 |     } | 
 |  | 
 | protected: | 
 |     virtual void setupPaint(SkPaint* paint) SK_OVERRIDE { | 
 |         this->INHERITED::setupPaint(paint); | 
 |         // srcmode is most interesting when we're not opaque | 
 |         paint->setAlpha(0x80); | 
 |         paint->setXfermode(fMode); | 
 |     } | 
 |  | 
 |     virtual const char* onGetName() SK_OVERRIDE { | 
 |         fName.set(this->INHERITED::onGetName()); | 
 |         fName.prepend("srcmode_"); | 
 |         return fName.c_str(); | 
 |     } | 
 |  | 
 | private: | 
 |     SkString fName; | 
 |     SkXfermode* fMode; | 
 |  | 
 |     typedef RectBench INHERITED; | 
 | }; | 
 |  | 
 | class OvalBench : public RectBench { | 
 | public: | 
 |     OvalBench(void* param, int shift, int stroke = 0) : RectBench(param, shift, stroke) {} | 
 | protected: | 
 |     virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) { | 
 |         c->drawOval(r, p); | 
 |     } | 
 |     virtual const char* onGetName() { return computeName("ovals"); } | 
 | }; | 
 |  | 
 | class RRectBench : public RectBench { | 
 | public: | 
 |     RRectBench(void* param, int shift, int stroke = 0) : RectBench(param, shift, stroke) {} | 
 | protected: | 
 |     virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) { | 
 |         c->drawRoundRect(r, r.width() / 4, r.height() / 4, p); | 
 |     } | 
 |     virtual const char* onGetName() { return computeName("rrects"); } | 
 | }; | 
 |  | 
 | class PointsBench : public RectBench { | 
 | public: | 
 |     SkCanvas::PointMode fMode; | 
 |     const char* fName; | 
 |  | 
 |     PointsBench(void* param, SkCanvas::PointMode mode, const char* name) : | 
 |         RectBench(param, 2), fMode(mode) { | 
 |         fName = name; | 
 |     } | 
 |  | 
 | protected: | 
 |     virtual void onDraw(SkCanvas* canvas) { | 
 |         SkScalar gSizes[] = { | 
 |             SkIntToScalar(7), 0 | 
 |         }; | 
 |         size_t sizes = SK_ARRAY_COUNT(gSizes); | 
 |  | 
 |         if (this->hasStrokeWidth()) { | 
 |             gSizes[0] = this->getStrokeWidth(); | 
 |             sizes = 1; | 
 |         } | 
 |  | 
 |         SkPaint paint; | 
 |         paint.setStrokeCap(SkPaint::kRound_Cap); | 
 |  | 
 |         for (size_t i = 0; i < sizes; i++) { | 
 |             paint.setStrokeWidth(gSizes[i]); | 
 |             this->setupPaint(&paint); | 
 |             canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint); | 
 |             paint.setColor(fColors[i]); | 
 |         } | 
 |     } | 
 |     virtual const char* onGetName() { return fName; } | 
 | }; | 
 |  | 
 | class AARectBench : public SkBenchmark { | 
 | public: | 
 |     enum { | 
 |         W = 640, | 
 |         H = 480, | 
 |     }; | 
 |  | 
 |     AARectBench(void* param, bool rotate) : INHERITED(param), fRotate(rotate) {} | 
 |  | 
 | protected: | 
 |  | 
 |     virtual const char* onGetName() { | 
 |         if (fRotate) { | 
 |             return "aarects_rotated"; | 
 |         } | 
 |         return "aarects"; | 
 |     } | 
 |  | 
 |     virtual void onDraw(SkCanvas* canvas) { | 
 |         static const SkScalar kHalfRectSize = SkFloatToScalar(0.75f); | 
 |  | 
 |         SkPaint paint; | 
 |         this->setupPaint(&paint); | 
 |         paint.setAntiAlias(true); | 
 |         paint.setColor(SK_ColorBLACK); | 
 |         SkRect r = { -kHalfRectSize, -kHalfRectSize, kHalfRectSize, kHalfRectSize }; | 
 |         int rot = 0; | 
 |  | 
 |         // Draw small aa rects in a grid across the screen | 
 |         for (SkScalar y = kHalfRectSize+SK_Scalar1; y < H; y += 2*kHalfRectSize+2) { | 
 |             for (SkScalar x = kHalfRectSize+SK_Scalar1; x < W; x += 2*kHalfRectSize+2) { | 
 |                 canvas->save(); | 
 |                 canvas->translate(x, y); | 
 |  | 
 |                 if (fRotate) { | 
 |                     SkMatrix rotate; | 
 |                     rotate.setRotate(SkIntToScalar(rot)); | 
 |                     canvas->concat(rotate); | 
 |                     rot += 10; | 
 |                 } | 
 |  | 
 |                 canvas->drawRect(r, paint); | 
 |                 canvas->restore(); | 
 |             } | 
 |         } | 
 |  | 
 |     } | 
 | private: | 
 |     bool fRotate; | 
 |     typedef SkBenchmark INHERITED; | 
 | }; | 
 |  | 
 | /******************************************************************************* | 
 |  * to bench BlitMask [Opaque, Black, color, shader] | 
 |  *******************************************************************************/ | 
 |  | 
 | class BlitMaskBench : public RectBench { | 
 | public: | 
 |     enum kMaskType { | 
 |         kMaskOpaque = 0, | 
 |         kMaskBlack, | 
 |         kMaskColor, | 
 |         KMaskShader | 
 |     }; | 
 |     SkCanvas::PointMode fMode; | 
 |     const char* fName; | 
 |  | 
 |     BlitMaskBench(void* param, SkCanvas::PointMode mode, | 
 |                   BlitMaskBench::kMaskType type, const char* name) : | 
 |                   RectBench(param, 2), fMode(mode), _type(type) { | 
 |         fName = name; | 
 |     } | 
 |  | 
 | protected: | 
 |     virtual void onDraw(SkCanvas* canvas) { | 
 |         SkScalar gSizes[] = { | 
 |             SkIntToScalar(13), SkIntToScalar(24) | 
 |         }; | 
 |         size_t sizes = SK_ARRAY_COUNT(gSizes); | 
 |  | 
 |         if (this->hasStrokeWidth()) { | 
 |             gSizes[0] = this->getStrokeWidth(); | 
 |             sizes = 1; | 
 |         } | 
 |         SkRandom rand; | 
 |         SkColor color = 0xFF000000; | 
 |         U8CPU alpha = 0xFF; | 
 |         SkPaint paint; | 
 |         paint.setStrokeCap(SkPaint::kRound_Cap); | 
 |         if (_type == KMaskShader) { | 
 |             SkBitmap srcBM; | 
 |             srcBM.setConfig(SkBitmap::kARGB_8888_Config, 10, 1); | 
 |             srcBM.allocPixels(); | 
 |             srcBM.eraseColor(0xFF00FF00); | 
 |  | 
 |             SkShader* s; | 
 |             s  = SkShader::CreateBitmapShader(srcBM, SkShader::kClamp_TileMode, | 
 |                                               SkShader::kClamp_TileMode); | 
 |             paint.setShader(s)->unref(); | 
 |         } | 
 |         for (size_t i = 0; i < sizes; i++) { | 
 |             switch (_type) { | 
 |                 case kMaskOpaque: | 
 |                     color = fColors[i]; | 
 |                     alpha = 0xFF; | 
 |                     break; | 
 |                 case kMaskBlack: | 
 |                     alpha = 0xFF; | 
 |                     color = 0xFF000000; | 
 |                     break; | 
 |                 case kMaskColor: | 
 |                     color = fColors[i]; | 
 |                     alpha = rand.nextU() & 255; | 
 |                     break; | 
 |                 case KMaskShader: | 
 |                     break; | 
 |             } | 
 |             paint.setStrokeWidth(gSizes[i]); | 
 |             this->setupPaint(&paint); | 
 |             paint.setColor(color); | 
 |             paint.setAlpha(alpha); | 
 |             canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint); | 
 |        } | 
 |     } | 
 |     virtual const char* onGetName() { return fName; } | 
 | private: | 
 |     typedef RectBench INHERITED; | 
 |     kMaskType _type; | 
 | }; | 
 |  | 
 |  | 
 | DEF_BENCH( return SkNEW_ARGS(RectBench, (p, 1)); ) | 
 | DEF_BENCH( return SkNEW_ARGS(RectBench, (p, 1, 4)); ) | 
 | DEF_BENCH( return SkNEW_ARGS(RectBench, (p, 3)); ) | 
 | DEF_BENCH( return SkNEW_ARGS(RectBench, (p, 3, 4)); ) | 
 | DEF_BENCH( return SkNEW_ARGS(OvalBench, (p, 1)); ) | 
 | DEF_BENCH( return SkNEW_ARGS(OvalBench, (p, 3)); ) | 
 | DEF_BENCH( return SkNEW_ARGS(OvalBench, (p, 1, 4)); ) | 
 | DEF_BENCH( return SkNEW_ARGS(OvalBench, (p, 3, 4)); ) | 
 | DEF_BENCH( return SkNEW_ARGS(RRectBench, (p, 1)); ) | 
 | DEF_BENCH( return SkNEW_ARGS(RRectBench, (p, 1, 4)); ) | 
 | DEF_BENCH( return SkNEW_ARGS(RRectBench, (p, 3)); ) | 
 | DEF_BENCH( return SkNEW_ARGS(RRectBench, (p, 3, 4)); ) | 
 | DEF_BENCH( return SkNEW_ARGS(PointsBench, (p, SkCanvas::kPoints_PointMode, "points")); ) | 
 | DEF_BENCH( return SkNEW_ARGS(PointsBench, (p, SkCanvas::kLines_PointMode, "lines")); ) | 
 | DEF_BENCH( return SkNEW_ARGS(PointsBench, (p, SkCanvas::kPolygon_PointMode, "polygon")); ) | 
 |  | 
 | DEF_BENCH( return SkNEW_ARGS(SrcModeRectBench, (p)); ) | 
 |  | 
 | DEF_BENCH( return SkNEW_ARGS(AARectBench, (p, false)); ) | 
 | DEF_BENCH( return SkNEW_ARGS(AARectBench, (p, true)); ) | 
 |  | 
 | /* init the blitmask bench | 
 |  */ | 
 | DEF_BENCH( return SkNEW_ARGS(BlitMaskBench, | 
 |                       (p, SkCanvas::kPoints_PointMode, | 
 |                       BlitMaskBench::kMaskOpaque, "maskopaque") | 
 |                       ); ) | 
 | DEF_BENCH( return SkNEW_ARGS(BlitMaskBench, | 
 |                       (p, SkCanvas::kPoints_PointMode, | 
 |                       BlitMaskBench::kMaskBlack, "maskblack") | 
 |                       ); ) | 
 | DEF_BENCH( return SkNEW_ARGS(BlitMaskBench, | 
 |                       (p, SkCanvas::kPoints_PointMode, | 
 |                       BlitMaskBench::kMaskColor, "maskcolor") | 
 |                       ); ) | 
 | DEF_BENCH( return SkNEW_ARGS(BlitMaskBench, | 
 |                      (p, SkCanvas::kPoints_PointMode, | 
 |                      BlitMaskBench::KMaskShader, "maskshader") | 
 |                      ); ) |