blob: 9e237a08d92c8d49ef7139eda976f11c7ea338ca [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();
Mike Reede02d7f82021-01-21 22:25:21 -050043 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);
Mike Klein5c612ad2020-08-26 12:26:06 -050047 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();
Mike Reed34c56a52021-01-22 15:26:41 -050075 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);
Mike Klein5c612ad2020-08-26 12:26:06 -050081 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};
96DEF_SAMPLE( return new TimingSample; )