• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "frame_painter.h"
17 
18 #include <map>
19 
20 #include "hilog/log.h"
21 #include "include/core/SkCanvas.h"
22 #include "include/core/SkColor.h"
23 
24 #include "frame_collector.h"
25 
26 namespace OHOS {
27 namespace Rosen {
28 namespace {
29 constexpr ::OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001400, "FramePainter" };
30 } // namespace
31 
FramePainter(FrameCollector & collector)32 FramePainter::FramePainter(FrameCollector &collector) : collector_(collector)
33 {
34 }
35 
Draw(SkCanvas & canvas)36 void FramePainter::Draw(SkCanvas &canvas)
37 {
38     if (collector_.IsEnabled() == false) {
39         return;
40     }
41 
42     auto width = canvas.imageInfo().width();
43     auto height = canvas.imageInfo().height();
44     ::OHOS::HiviewDFX::HiLog::Debug(LABEL, "FramePainter::Draw %{public}dx%{public}d", width, height);
45 
46     constexpr auto normalFPS = 60;
47     constexpr auto slowFPS = normalFPS / 2;
48     auto bars = GenerateTimeBars(width, height, normalFPS);
49     SkPaint paint;
50     paint.setStyle(paint.kFill_Style);
51     for (const auto &[isHeavy, color, x, y, w, h] : bars) {
52         constexpr uint32_t heavyFrameAlpha = 0x7f;
53         constexpr uint32_t lightFrameAlpha = 0x3f;
54         auto alpha = isHeavy ? heavyFrameAlpha : lightFrameAlpha;
55         constexpr uint32_t alphaOffset = 24; // ARGB
56         paint.setColor(color | (alpha << alphaOffset));
57         canvas.drawRect(SkRect::MakeXYWH(x, y, w, h), paint);
58     }
59 
60     // normal fps line: alpha: 0xbf, green #00ff00
61     DrawFPSLine(canvas, normalFPS, height / frameTotalMs, 0xbf00ff00);
62 
63     // slow fps line: alpha: 0xbf, red #ff0000
64     DrawFPSLine(canvas, slowFPS, height / frameTotalMs, 0xbfff0000);
65 }
66 
DrawFPSLine(SkCanvas & canvas,uint32_t fps,double thickness,uint32_t color)67 void FramePainter::DrawFPSLine(SkCanvas &canvas, uint32_t fps, double thickness, uint32_t color)
68 {
69     if (fps == 0) {
70         return;
71     }
72 
73     auto width = canvas.imageInfo().width();
74     auto height = canvas.imageInfo().height();
75     auto heightPerMs = height / frameTotalMs;
76 
77     constexpr auto OneSecondInMs = 1000.0;
78     auto bottom = OneSecondInMs / fps * heightPerMs;
79     auto lineOffset = thickness / 0x2; // vertical align center
80     auto fpsLine = SkRect::MakeXYWH(0, height - (bottom - lineOffset), width, thickness);
81 
82     SkPaint paint;
83     paint.setStyle(paint.kFill_Style);
84     paint.setColor(color);
85     canvas.drawRect(fpsLine, paint);
86 }
87 
GenerateTimeBars(uint32_t width,uint32_t height,uint32_t fps)88 std::vector<struct FramePainter::TimeBar> FramePainter::GenerateTimeBars(
89     uint32_t width, uint32_t height, uint32_t fps)
90 {
91     std::vector<struct TimeBar> bars;
92 
93     auto heightPerMs = height / frameTotalMs;
94     constexpr auto reservedSize = 2.0;
95     auto barWidth = width / (frameQueueMaxSize + reservedSize);
96     auto offsetX = barWidth * frameQueueMaxSize - barWidth;
97 
98     auto frameQueue = collector_.LockGetFrameQueue();
99     for (auto rit = frameQueue.rbegin(); rit != frameQueue.rend(); rit++) {
100         constexpr auto OneSecondInMs = 1000.0;
101         auto isHeavy = SumTimesInMs(*rit) >= (OneSecondInMs / fps);
102         auto offsetY = height;
103         constexpr auto loopstart = static_cast<size_t>(FrameEventType::LoopStart);
104         constexpr auto loopend = static_cast<size_t>(FrameEventType::LoopEnd);
105         constexpr size_t frameEventTypeInterval = 2;
106         for (size_t i = loopstart; i < loopend; i += frameEventTypeInterval) {
107             auto it = frameEventColorMap.find(static_cast<FrameEventType>(i));
108             if (it == frameEventColorMap.end()) {
109                 continue;
110             }
111             auto color = it->second;
112 
113             constexpr double nanosecondsToMilliseconds = 1e6;
114             double diffMs = (rit->times[i + 1] - rit->times[i]) / nanosecondsToMilliseconds;
115             if (diffMs < 0) {
116                 ::OHOS::HiviewDFX::HiLog::Warn(LABEL, "FramePainter::Draw %{public}zu range is negative", i);
117                 continue;
118             } else if (diffMs == 0) {
119                 continue;
120             }
121 
122             auto diffHeight = diffMs * heightPerMs;
123             offsetY -= diffHeight;
124             struct TimeBar bar = {
125                 .isHeavy = isHeavy,
126                 .color = color,
127                 .posX = offsetX,
128                 .posY = offsetY,
129                 .width = barWidth,
130                 .height = diffHeight,
131             };
132             bars.push_back(bar);
133         }
134         offsetX -= barWidth;
135     }
136     collector_.UnlockFrameQueue();
137 
138     return bars;
139 }
140 
SumTimesInMs(const struct FrameInfo & info)141 double FramePainter::SumTimesInMs(const struct FrameInfo &info)
142 {
143     auto sumMs = 0.0;
144     constexpr auto loopstart = static_cast<size_t>(FrameEventType::LoopStart);
145     constexpr auto loopend = static_cast<size_t>(FrameEventType::LoopEnd);
146     constexpr size_t frameEventTypeInterval = 2;
147     for (size_t i = loopstart; i < loopend; i += frameEventTypeInterval) {
148         const auto &cm = frameEventColorMap;
149         if (cm.find(static_cast<FrameEventType>(i)) == cm.end()) {
150             continue;
151         }
152 
153         constexpr double nanosecondsToMilliseconds = 1e6;
154         double diffMs = (info.times[i + 1] - info.times[i]) / nanosecondsToMilliseconds;
155         if (diffMs <= 0) {
156             continue;
157         }
158 
159         sumMs += diffMs;
160     }
161 
162     return sumMs;
163 }
164 } // namespace Rosen
165 } // namespace OHOS
166