| /* |
| * Copyright 2020 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "include/core/SkCanvas.h" |
| #include "include/core/SkFont.h" |
| #include "include/core/SkSurface.h" |
| #include "tools/fonts/FontToolUtils.h" |
| #include "tools/viewer/Slide.h" |
| |
| #include <chrono> |
| |
| class TimingSlide : public Slide { |
| public: |
| TimingSlide() { fName = "Timing";} |
| |
| void load(SkScalar w, SkScalar h) override { |
| sk_sp<SkSurface> surf = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(W, H)); |
| surf->getCanvas()->drawString("abc", 2,H-4, ToolUtils::DefaultFont(), SkPaint{}); |
| fImg = surf->makeImageSnapshot(); |
| } |
| |
| void draw(SkCanvas* canvas) override { |
| canvas->scale(8,8); |
| |
| // Draw normally. |
| canvas->drawImage(fImg, 0,0); |
| |
| canvas->translate(0,H); |
| |
| // Draw one pixel at a time with drawImageRect(), |
| // timing how long each drawImageRect() call takes. |
| double cost[H][W]; |
| double min = +INFINITY, |
| max = -INFINITY; |
| for (int y = 0; y < H; y++) |
| for (int x = 0; x < W; x++) { |
| auto start = std::chrono::steady_clock::now(); |
| canvas->drawImageRect(fImg.get(), |
| SkRect::MakeXYWH(x,y,1,1), SkRect::MakeXYWH(x,y,1,1), |
| SkSamplingOptions(), /*paint=*/nullptr, |
| SkCanvas::kStrict_SrcRectConstraint); |
| auto elapsed = std::chrono::steady_clock::now() - start; |
| |
| cost[y][x] = elapsed.count(); |
| min = std::min(min, cost[y][x]); |
| max = std::max(max, cost[y][x]); |
| } |
| |
| canvas->translate(0,H); |
| |
| // Draw using those per-pixel timings, |
| // with the slowest pixel scaled to alpha=1, the fastest to alpha=0. |
| for (int y = 0; y < H; y++) |
| for (int x = 0; x < W; x++) { |
| SkPaint p; |
| p.setAlphaf( (cost[y][x] - min) / (max - min) ); |
| canvas->drawRect(SkRect::MakeXYWH(x,y,1,1), p); |
| } |
| |
| canvas->translate(0,H); |
| |
| // Draw each pixel into offscreen, timing each draw. |
| SkImageInfo info = canvas->imageInfo().makeWH(1024,1024); |
| if (sk_sp<SkSurface> offscreen = canvas->makeSurface(info)) { |
| min = +INFINITY; |
| max = -INFINITY; |
| for (int y = 0; y < H; y++) |
| for (int x = 0; x < W; x++) { |
| auto start = std::chrono::steady_clock::now(); |
| offscreen->getCanvas()->drawImageRect(fImg, |
| SkRect::MakeXYWH(x,y,1,1), |
| SkRect::MakeXYWH(0,0,1024,1024), |
| SkSamplingOptions(), |
| /*paint=*/nullptr, |
| SkCanvas::kStrict_SrcRectConstraint); |
| auto elapsed = std::chrono::steady_clock::now() - start; |
| |
| cost[y][x] = elapsed.count(); |
| min = std::min(min, cost[y][x]); |
| max = std::max(max, cost[y][x]); |
| } |
| for (int y = 0; y < H; y++) |
| for (int x = 0; x < W; x++) { |
| SkPaint p; |
| p.setAlphaf( (cost[y][x] - min) / (max - min) ); |
| canvas->drawRect(SkRect::MakeXYWH(x,y,1,1), p); |
| } |
| } |
| } |
| private: |
| inline static constexpr int W = 24, |
| H = 16; |
| sk_sp<SkImage> fImg; |
| }; |
| |
| DEF_SLIDE( return new TimingSlide; ) |