1 /* 2 * Copyright 2020 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 "include/core/SkCanvas.h" 9 #include "include/core/SkFont.h" 10 #include "include/core/SkSurface.h" 11 #include "tools/fonts/FontToolUtils.h" 12 #include "tools/viewer/Slide.h" 13 14 #include <chrono> 15 16 class TimingSlide : public Slide { 17 public: TimingSlide()18 TimingSlide() { fName = "Timing";} 19 load(SkScalar w,SkScalar h)20 void load(SkScalar w, SkScalar h) override { 21 sk_sp<SkSurface> surf = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(W, H)); 22 surf->getCanvas()->drawString("abc", 2,H-4, ToolUtils::DefaultFont(), SkPaint{}); 23 fImg = surf->makeImageSnapshot(); 24 } 25 draw(SkCanvas * canvas)26 void draw(SkCanvas* canvas) override { 27 canvas->scale(8,8); 28 29 // Draw normally. 30 canvas->drawImage(fImg, 0,0); 31 32 canvas->translate(0,H); 33 34 // Draw one pixel at a time with drawImageRect(), 35 // timing how long each drawImageRect() call takes. 36 double cost[H][W]; 37 double min = +INFINITY, 38 max = -INFINITY; 39 for (int y = 0; y < H; y++) 40 for (int x = 0; x < W; x++) { 41 auto start = std::chrono::steady_clock::now(); 42 canvas->drawImageRect(fImg.get(), 43 SkRect::MakeXYWH(x,y,1,1), SkRect::MakeXYWH(x,y,1,1), 44 SkSamplingOptions(), /*paint=*/nullptr, 45 SkCanvas::kStrict_SrcRectConstraint); 46 auto elapsed = std::chrono::steady_clock::now() - start; 47 48 cost[y][x] = elapsed.count(); 49 min = std::min(min, cost[y][x]); 50 max = std::max(max, cost[y][x]); 51 } 52 53 canvas->translate(0,H); 54 55 // Draw using those per-pixel timings, 56 // with the slowest pixel scaled to alpha=1, the fastest to alpha=0. 57 for (int y = 0; y < H; y++) 58 for (int x = 0; x < W; x++) { 59 SkPaint p; 60 p.setAlphaf( (cost[y][x] - min) / (max - min) ); 61 canvas->drawRect(SkRect::MakeXYWH(x,y,1,1), p); 62 } 63 64 canvas->translate(0,H); 65 66 // Draw each pixel into offscreen, timing each draw. 67 SkImageInfo info = canvas->imageInfo().makeWH(1024,1024); 68 if (sk_sp<SkSurface> offscreen = canvas->makeSurface(info)) { 69 min = +INFINITY; 70 max = -INFINITY; 71 for (int y = 0; y < H; y++) 72 for (int x = 0; x < W; x++) { 73 auto start = std::chrono::steady_clock::now(); 74 offscreen->getCanvas()->drawImageRect(fImg, 75 SkRect::MakeXYWH(x,y,1,1), 76 SkRect::MakeXYWH(0,0,1024,1024), 77 SkSamplingOptions(), 78 /*paint=*/nullptr, 79 SkCanvas::kStrict_SrcRectConstraint); 80 auto elapsed = std::chrono::steady_clock::now() - start; 81 82 cost[y][x] = elapsed.count(); 83 min = std::min(min, cost[y][x]); 84 max = std::max(max, cost[y][x]); 85 } 86 for (int y = 0; y < H; y++) 87 for (int x = 0; x < W; x++) { 88 SkPaint p; 89 p.setAlphaf( (cost[y][x] - min) / (max - min) ); 90 canvas->drawRect(SkRect::MakeXYWH(x,y,1,1), p); 91 } 92 } 93 } 94 private: 95 inline static constexpr int W = 24, 96 H = 16; 97 sk_sp<SkImage> fImg; 98 }; 99 100 DEF_SLIDE( return new TimingSlide; ) 101