1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2020 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 9cb93a386Sopenharmony_ci#include "include/core/SkFont.h" 10cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 11cb93a386Sopenharmony_ci#include "samplecode/Sample.h" 12cb93a386Sopenharmony_ci#include <chrono> 13cb93a386Sopenharmony_ci 14cb93a386Sopenharmony_cistruct TimingSample : public Sample { 15cb93a386Sopenharmony_ci inline static constexpr int W = 24, 16cb93a386Sopenharmony_ci H = 16; 17cb93a386Sopenharmony_ci sk_sp<SkImage> fImg; 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci SkString name() override { return SkString("Timing"); } 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci void onOnceBeforeDraw() override { 22cb93a386Sopenharmony_ci sk_sp<SkSurface> surf = SkSurface::MakeRasterN32Premul(W,H); 23cb93a386Sopenharmony_ci surf->getCanvas()->drawString("abc", 2,H-4, SkFont{}, SkPaint{}); 24cb93a386Sopenharmony_ci fImg = surf->makeImageSnapshot(); 25cb93a386Sopenharmony_ci } 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci void onDrawContent(SkCanvas* canvas) override { 28cb93a386Sopenharmony_ci canvas->scale(8,8); 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci // Draw normally. 31cb93a386Sopenharmony_ci canvas->drawImage(fImg, 0,0); 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ci canvas->translate(0,H); 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci // Draw one pixel at a time with drawImageRect(), 36cb93a386Sopenharmony_ci // timing how long each drawImageRect() call takes. 37cb93a386Sopenharmony_ci double cost[H][W]; 38cb93a386Sopenharmony_ci double min = +INFINITY, 39cb93a386Sopenharmony_ci max = -INFINITY; 40cb93a386Sopenharmony_ci for (int y = 0; y < H; y++) 41cb93a386Sopenharmony_ci for (int x = 0; x < W; x++) { 42cb93a386Sopenharmony_ci auto start = std::chrono::steady_clock::now(); 43cb93a386Sopenharmony_ci canvas->drawImageRect(fImg.get(), 44cb93a386Sopenharmony_ci SkRect::MakeXYWH(x,y,1,1), SkRect::MakeXYWH(x,y,1,1), 45cb93a386Sopenharmony_ci SkSamplingOptions(), /*paint=*/nullptr, 46cb93a386Sopenharmony_ci SkCanvas::kStrict_SrcRectConstraint); 47cb93a386Sopenharmony_ci auto elapsed = std::chrono::steady_clock::now() - start; 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci cost[y][x] = elapsed.count(); 50cb93a386Sopenharmony_ci min = std::min(min, cost[y][x]); 51cb93a386Sopenharmony_ci max = std::max(max, cost[y][x]); 52cb93a386Sopenharmony_ci } 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci canvas->translate(0,H); 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci // Draw using those per-pixel timings, 57cb93a386Sopenharmony_ci // with the slowest pixel scaled to alpha=1, the fastest to alpha=0. 58cb93a386Sopenharmony_ci for (int y = 0; y < H; y++) 59cb93a386Sopenharmony_ci for (int x = 0; x < W; x++) { 60cb93a386Sopenharmony_ci SkPaint p; 61cb93a386Sopenharmony_ci p.setAlphaf( (cost[y][x] - min) / (max - min) ); 62cb93a386Sopenharmony_ci canvas->drawRect(SkRect::MakeXYWH(x,y,1,1), p); 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci canvas->translate(0,H); 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci // Draw each pixel into offscreen, timing each draw. 68cb93a386Sopenharmony_ci SkImageInfo info = canvas->imageInfo().makeWH(1024,1024); 69cb93a386Sopenharmony_ci if (sk_sp<SkSurface> offscreen = canvas->makeSurface(info)) { 70cb93a386Sopenharmony_ci min = +INFINITY; 71cb93a386Sopenharmony_ci max = -INFINITY; 72cb93a386Sopenharmony_ci for (int y = 0; y < H; y++) 73cb93a386Sopenharmony_ci for (int x = 0; x < W; x++) { 74cb93a386Sopenharmony_ci auto start = std::chrono::steady_clock::now(); 75cb93a386Sopenharmony_ci offscreen->getCanvas()->drawImageRect(fImg, 76cb93a386Sopenharmony_ci SkRect::MakeXYWH(x,y,1,1), 77cb93a386Sopenharmony_ci SkRect::MakeXYWH(0,0,1024,1024), 78cb93a386Sopenharmony_ci SkSamplingOptions(), 79cb93a386Sopenharmony_ci /*paint=*/nullptr, 80cb93a386Sopenharmony_ci SkCanvas::kStrict_SrcRectConstraint); 81cb93a386Sopenharmony_ci auto elapsed = std::chrono::steady_clock::now() - start; 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ci cost[y][x] = elapsed.count(); 84cb93a386Sopenharmony_ci min = std::min(min, cost[y][x]); 85cb93a386Sopenharmony_ci max = std::max(max, cost[y][x]); 86cb93a386Sopenharmony_ci } 87cb93a386Sopenharmony_ci for (int y = 0; y < H; y++) 88cb93a386Sopenharmony_ci for (int x = 0; x < W; x++) { 89cb93a386Sopenharmony_ci SkPaint p; 90cb93a386Sopenharmony_ci p.setAlphaf( (cost[y][x] - min) / (max - min) ); 91cb93a386Sopenharmony_ci canvas->drawRect(SkRect::MakeXYWH(x,y,1,1), p); 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci}; 96cb93a386Sopenharmony_ciDEF_SAMPLE( return new TimingSample; ) 97