• 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         auto isHeavy = SumTimesInMs(*rit) >= (OneSecondInMs / fps);
143         auto offsetY = height;
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             auto it = frameEventColorMap.find(static_cast<FrameEventType>(i));
149             if (it == frameEventColorMap.end()) {
150                 continue;
151             }
152             auto color = it->second;
153 
154             constexpr double nanosecondsToMilliseconds = 1e6;
155             double diffMs = (rit->times[i + 1] - rit->times[i]) / nanosecondsToMilliseconds;
156             if (diffMs < 0) {
157                 ::OHOS::HiviewDFX::HiLog::Warn(LABEL, "FramePainter::Draw %{public}zu range is negative", i);
158                 continue;
159             } else if (diffMs == 0) {
160                 continue;
161             }
162 
163             auto diffHeight = diffMs * heightPerMs;
164             offsetY -= diffHeight;
165             struct TimeBar bar = {
166                 .isHeavy = isHeavy,
167                 .color = color,
168                 .posX = offsetX,
169                 .posY = offsetY,
170                 .width = barWidth,
171                 .height = diffHeight,
172             };
173             bars.push_back(bar);
174         }
175         offsetX -= barWidth;
176     }
177     collector_.UnlockFrameQueue();
178 
179     return bars;
180 }
181 
SumTimesInMs(const struct FrameInfo & info)182 double FramePainter::SumTimesInMs(const struct FrameInfo &info)
183 {
184     auto sumMs = 0.0;
185     constexpr auto loopstart = static_cast<size_t>(FrameEventType::LoopStart);
186     constexpr auto loopend = static_cast<size_t>(FrameEventType::LoopEnd);
187     constexpr size_t frameEventTypeInterval = 2;
188     for (size_t i = loopstart; i < loopend; i += frameEventTypeInterval) {
189         const auto &cm = frameEventColorMap;
190         if (cm.find(static_cast<FrameEventType>(i)) == cm.end()) {
191             continue;
192         }
193 
194         constexpr double nanosecondsToMilliseconds = 1e6;
195         double diffMs = (info.times[i + 1] - info.times[i]) / nanosecondsToMilliseconds;
196         if (diffMs <= 0) {
197             continue;
198         }
199 
200         sumMs += diffMs;
201     }
202 
203     return sumMs;
204 }
205 } // namespace Rosen
206 } // namespace OHOS
207