• 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 #ifndef USE_ROSEN_DRAWING
22 #include "include/core/SkCanvas.h"
23 #include "include/core/SkColor.h"
24 #endif
25 
26 #include "frame_collector.h"
27 
28 namespace OHOS {
29 namespace Rosen {
30 namespace {
31 constexpr ::OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001400, "FramePainter" };
32 } // namespace
33 
FramePainter(FrameCollector & collector)34 FramePainter::FramePainter(FrameCollector &collector) : collector_(collector)
35 {
36 }
37 
38 #ifndef USE_ROSEN_DRAWING
Draw(SkCanvas & canvas)39 void FramePainter::Draw(SkCanvas &canvas)
40 #else
41 void FramePainter::Draw(Drawing::Canvas &canvas)
42 #endif
43 {
44     if (collector_.IsEnabled() == false) {
45         return;
46     }
47 
48 #ifndef USE_ROSEN_DRAWING
49     auto width = canvas.imageInfo().width();
50     auto height = canvas.imageInfo().height();
51 #else
52     auto width = canvas.GetWidth();
53     auto height = canvas.GetHeight();
54 #endif
55     ::OHOS::HiviewDFX::HiLog::Debug(LABEL, "FramePainter::Draw %{public}dx%{public}d", width, height);
56 
57     constexpr auto normalFPS = 60;
58     constexpr auto slowFPS = normalFPS / 2;
59     auto bars = GenerateTimeBars(width, height, normalFPS);
60 #ifndef USE_ROSEN_DRAWING
61     SkPaint paint;
62     paint.setStyle(paint.kFill_Style);
63 #else
64     Drawing::Brush brush;
65 #endif
66     for (const auto &[isHeavy, color, x, y, w, h] : bars) {
67         constexpr uint32_t heavyFrameAlpha = 0x7f;
68         constexpr uint32_t lightFrameAlpha = 0x3f;
69         auto alpha = isHeavy ? heavyFrameAlpha : lightFrameAlpha;
70         constexpr uint32_t alphaOffset = 24; // ARGB
71 #ifndef USE_ROSEN_DRAWING
72         paint.setColor(color | (alpha << alphaOffset));
73         canvas.drawRect(SkRect::MakeXYWH(x, y, w, h), paint);
74 #else
75         brush.SetColor(color | (alpha << alphaOffset));
76         canvas.AttachBrush(brush);
77         canvas.DrawRect(Drawing::Rect(x, y, w + x, h + y));
78         canvas.DetachBrush();
79 #endif
80     }
81 
82     // normal fps line: alpha: 0xbf, green #00ff00
83     DrawFPSLine(canvas, normalFPS, height / frameTotalMs, 0xbf00ff00);
84 
85     // slow fps line: alpha: 0xbf, red #ff0000
86     DrawFPSLine(canvas, slowFPS, height / frameTotalMs, 0xbfff0000);
87 }
88 
89 #ifndef USE_ROSEN_DRAWING
DrawFPSLine(SkCanvas & canvas,uint32_t fps,double thickness,uint32_t color)90 void FramePainter::DrawFPSLine(SkCanvas &canvas, uint32_t fps, double thickness, uint32_t color)
91 #else
92 void FramePainter::DrawFPSLine(Drawing::Canvas &canvas, uint32_t fps, double thickness, uint32_t color)
93 #endif
94 {
95     if (fps == 0) {
96         return;
97     }
98 
99 #ifndef USE_ROSEN_DRAWING
100     auto width = canvas.imageInfo().width();
101     auto height = canvas.imageInfo().height();
102 #else
103     auto width = canvas.GetWidth();
104     auto height = canvas.GetHeight();
105 #endif
106     auto heightPerMs = height / frameTotalMs;
107 
108     constexpr auto OneSecondInMs = 1000.0;
109     auto bottom = OneSecondInMs / fps * heightPerMs;
110     auto lineOffset = thickness / 0x2; // vertical align center
111 #ifndef USE_ROSEN_DRAWING
112     auto fpsLine = SkRect::MakeXYWH(0, height - (bottom - lineOffset), width, thickness);
113 
114     SkPaint paint;
115     paint.setStyle(paint.kFill_Style);
116     paint.setColor(color);
117     canvas.drawRect(fpsLine, paint);
118 #else
119     auto fpsLine = Drawing::Rect(0, height - (bottom - lineOffset), width, thickness + height - (bottom - lineOffset));
120 
121     Drawing::Brush brush;
122     brush.SetColor(color);
123     canvas.AttachBrush(brush);
124     canvas.DrawRect(fpsLine);
125     canvas.DetachBrush();
126 #endif
127 }
128 
GenerateTimeBars(uint32_t width,uint32_t height,uint32_t fps)129 std::vector<struct FramePainter::TimeBar> FramePainter::GenerateTimeBars(
130     uint32_t width, uint32_t height, uint32_t fps)
131 {
132     std::vector<struct TimeBar> bars;
133 
134     auto heightPerMs = height / frameTotalMs;
135     constexpr auto reservedSize = 2.0;
136     auto barWidth = width / (frameQueueMaxSize + reservedSize);
137     auto offsetX = barWidth * frameQueueMaxSize - barWidth;
138 
139     auto frameQueue = collector_.LockGetFrameQueue();
140     for (auto rit = frameQueue.rbegin(); rit != frameQueue.rend(); rit++) {
141         constexpr auto OneSecondInMs = 1000.0;
142         bool isHeavy = false;
143         if (fps != 0) {
144             isHeavy = SumTimesInMs(*rit) >= (OneSecondInMs / fps);
145         }
146         auto offsetY = height;
147         constexpr auto loopstart = static_cast<size_t>(FrameEventType::LoopStart);
148         constexpr auto loopend = static_cast<size_t>(FrameEventType::LoopEnd);
149         constexpr size_t frameEventTypeInterval = 2;
150         for (size_t i = loopstart; i < loopend; i += frameEventTypeInterval) {
151             auto it = frameEventColorMap.find(static_cast<FrameEventType>(i));
152             if (it == frameEventColorMap.end()) {
153                 continue;
154             }
155             auto color = it->second;
156 
157             constexpr double nanosecondsToMilliseconds = 1e6;
158             double diffMs = (rit->times[i + 1] - rit->times[i]) / nanosecondsToMilliseconds;
159             if (diffMs < 0) {
160                 ::OHOS::HiviewDFX::HiLog::Warn(LABEL, "FramePainter::Draw %{public}zu range is negative", i);
161                 continue;
162             } else if (diffMs == 0) {
163                 continue;
164             }
165 
166             auto diffHeight = diffMs * heightPerMs;
167             offsetY -= diffHeight;
168             struct TimeBar bar = {
169                 .isHeavy = isHeavy,
170                 .color = color,
171                 .posX = offsetX,
172                 .posY = offsetY,
173                 .width = barWidth,
174                 .height = diffHeight,
175             };
176             bars.push_back(bar);
177         }
178         offsetX -= barWidth;
179     }
180     collector_.UnlockFrameQueue();
181 
182     return bars;
183 }
184 
SumTimesInMs(const struct FrameInfo & info)185 double FramePainter::SumTimesInMs(const struct FrameInfo &info)
186 {
187     auto sumMs = 0.0;
188     constexpr auto loopstart = static_cast<size_t>(FrameEventType::LoopStart);
189     constexpr auto loopend = static_cast<size_t>(FrameEventType::LoopEnd);
190     constexpr size_t frameEventTypeInterval = 2;
191     for (size_t i = loopstart; i < loopend; i += frameEventTypeInterval) {
192         const auto &cm = frameEventColorMap;
193         if (cm.find(static_cast<FrameEventType>(i)) == cm.end()) {
194             continue;
195         }
196 
197         constexpr double nanosecondsToMilliseconds = 1e6;
198         double diffMs = (info.times[i + 1] - info.times[i]) / nanosecondsToMilliseconds;
199         if (diffMs <= 0) {
200             continue;
201         }
202 
203         sumMs += diffMs;
204     }
205 
206     return sumMs;
207 }
208 } // namespace Rosen
209 } // namespace OHOS
210