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