blob: 4dce6d1b7cf3e5010577d9c1e468a1c2d1c2643e [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();
75 offscreen->getCanvas()->drawImageRect(fImg, SkRect::MakeXYWH(x,y,1,1)
76 , SkRect::MakeXYWH(0,0,1024,1024)
77 , /*paint=*/nullptr);
78 auto elapsed = std::chrono::steady_clock::now() - start;
79
80 cost[y][x] = elapsed.count();
81 min = std::min(min, cost[y][x]);
82 max = std::max(max, cost[y][x]);
83 }
84 for (int y = 0; y < H; y++)
85 for (int x = 0; x < W; x++) {
86 SkPaint p;
87 p.setAlphaf( (cost[y][x] - min) / (max - min) );
88 canvas->drawRect(SkRect::MakeXYWH(x,y,1,1), p);
89 }
90 }
91 }
92};
93DEF_SAMPLE( return new TimingSample; )