blob: e4c9ad1edff5343a232670f6629dd3297d23ae2f [file] [log] [blame]
Mike Klein5c612ad2020-08-26 12:26:06 -05001/*
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
14struct TimingSample : public Sample {
15 static constexpr int W = 24,
16 H = 16;
17 sk_sp<SkImage> fImg;
18
19 SkString name() override { return SkString("Timing"); }
20
21 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
27 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, SkRect::MakeXYWH(x,y,1,1)
44 , SkRect::MakeXYWH(x,y,1,1)
45 , /*paint=*/nullptr);
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, SkRect::MakeXYWH(x,y,1,1)
75 , SkRect::MakeXYWH(0,0,1024,1024)
76 , /*paint=*/nullptr);
77 auto elapsed = std::chrono::steady_clock::now() - start;
78
79 cost[y][x] = elapsed.count();
80 min = std::min(min, cost[y][x]);
81 max = std::max(max, cost[y][x]);
82 }
83 for (int y = 0; y < H; y++)
84 for (int x = 0; x < W; x++) {
85 SkPaint p;
86 p.setAlphaf( (cost[y][x] - min) / (max - min) );
87 canvas->drawRect(SkRect::MakeXYWH(x,y,1,1), p);
88 }
89 }
90 }
91};
92DEF_SAMPLE( return new TimingSample; )