1/* 2 * Copyright 2013 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 "bench/Benchmark.h" 9#include "include/core/SkCanvas.h" 10#include "include/core/SkFont.h" 11#include "include/core/SkPaint.h" 12#include "include/core/SkString.h" 13#include "include/core/SkTextBlob.h" 14#include "include/utils/SkRandom.h" 15#include "src/core/SkBlendModePriv.h" 16#include "tools/Resources.h" 17 18namespace { 19enum Type { 20 kText, 21 kRect, 22 kSprite, 23}; 24} 25 26const char* gTypeNames[] = { 27 "mask", "rect", "sprite", 28}; 29 30// Benchmark that draws non-AA rects or AA text with an SkXfermode::Mode. 31class XfermodeBench : public Benchmark { 32public: 33 XfermodeBench(SkBlendMode mode, Type t) : fBlendMode(mode) { 34 fType = t; 35 fName.printf("blendmicro_%s_%s", gTypeNames[t], SkBlendMode_Name(mode)); 36 } 37 38protected: 39 const char* onGetName() override { return fName.c_str(); } 40 41 void onDelayedSetup() override { 42 if (fType == kSprite) { 43 fImage = GetResourceAsImage("images/color_wheel.png"); 44 } 45 } 46 47 void onDraw(int loops, SkCanvas* canvas) override { 48 const char* text = "Hamburgefons"; 49 size_t len = strlen(text); 50 SkISize size = canvas->getBaseLayerSize(); 51 SkRandom random; 52 while (loops > 0) { 53 SkPaint paint; 54 paint.setBlendMode(fBlendMode); 55 paint.setColor(random.nextU()); 56 switch (fType) { 57 case kText: { 58 // Draw text to exercise AA code paths. 59 SkFont font; 60 font.setSize(random.nextRangeScalar(12, 96)); 61 SkScalar x = random.nextRangeScalar(0, (SkScalar)size.fWidth), 62 y = random.nextRangeScalar(0, (SkScalar)size.fHeight); 63 auto blob = SkTextBlob::MakeFromText(text, len, font, SkTextEncoding::kUTF8); 64 int iterations = std::min(1000, loops); 65 for (int j = 0; j < iterations; ++j) { 66 canvas->drawTextBlob(blob, x, y, paint); 67 } 68 loops -= iterations; 69 } break; 70 case kRect: { 71 // Draw rects to exercise non-AA code paths. 72 SkScalar w = random.nextRangeScalar(50, 100); 73 SkScalar h = random.nextRangeScalar(50, 100); 74 SkRect rect = SkRect::MakeXYWH( 75 random.nextUScalar1() * (size.fWidth - w), 76 random.nextUScalar1() * (size.fHeight - h), 77 w, 78 h 79 ); 80 int iterations = std::min(1000, loops); 81 for (int j = 0; j < iterations; ++j) { 82 canvas->drawRect(rect, paint); 83 } 84 loops -= iterations; 85 } break; 86 case kSprite: 87 paint.setAlphaf(1.0f); 88 for (int i = 0; i < 10; ++i) { 89 canvas->drawImage(fImage, 0, 0, SkSamplingOptions(), &paint); 90 } 91 loops -= 1; 92 break; 93 } 94 } 95 } 96 97 bool isSuitableFor(Backend backend) override { 98 return backend == kRaster_Backend; 99 } 100 101private: 102 SkBlendMode fBlendMode; 103 SkString fName; 104 sk_sp<SkImage> fImage; 105 Type fType; 106 107 using INHERITED = Benchmark; 108}; 109 110////////////////////////////////////////////////////////////////////////////// 111 112#define BENCH(mode) \ 113 DEF_BENCH( return new XfermodeBench(mode, kText); ) \ 114 DEF_BENCH( return new XfermodeBench(mode, kRect); ) \ 115 DEF_BENCH( return new XfermodeBench(mode, kSprite); ) 116 117BENCH(SkBlendMode::kClear) 118BENCH(SkBlendMode::kSrc) 119BENCH(SkBlendMode::kDst) 120BENCH(SkBlendMode::kSrcOver) 121BENCH(SkBlendMode::kDstOver) 122BENCH(SkBlendMode::kSrcIn) 123BENCH(SkBlendMode::kDstIn) 124BENCH(SkBlendMode::kSrcOut) 125BENCH(SkBlendMode::kDstOut) 126BENCH(SkBlendMode::kSrcATop) 127BENCH(SkBlendMode::kDstATop) 128BENCH(SkBlendMode::kXor) 129 130BENCH(SkBlendMode::kPlus) 131BENCH(SkBlendMode::kModulate) 132BENCH(SkBlendMode::kScreen) 133 134BENCH(SkBlendMode::kOverlay) 135BENCH(SkBlendMode::kDarken) 136BENCH(SkBlendMode::kLighten) 137BENCH(SkBlendMode::kColorDodge) 138BENCH(SkBlendMode::kColorBurn) 139BENCH(SkBlendMode::kHardLight) 140BENCH(SkBlendMode::kSoftLight) 141BENCH(SkBlendMode::kDifference) 142BENCH(SkBlendMode::kExclusion) 143BENCH(SkBlendMode::kMultiply) 144 145BENCH(SkBlendMode::kHue) 146BENCH(SkBlendMode::kSaturation) 147BENCH(SkBlendMode::kColor) 148BENCH(SkBlendMode::kLuminosity) 149