/* * 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 "samplecode/Sample.h" #include <chrono> struct TimingSample : public Sample { static constexpr int W = 24, H = 16; sk_sp<SkImage> fImg; SkString name() override { return SkString("Timing"); } void onOnceBeforeDraw() override { sk_sp<SkSurface> surf = SkSurface::MakeRasterN32Premul(W,H); surf->getCanvas()->drawString("abc", 2,H-4, SkFont{}, SkPaint{}); fImg = surf->makeImageSnapshot(); } void onDrawContent(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); } } } }; DEF_SAMPLE( return new TimingSample; )