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