1 /*
2 * Copyright (c) 2025 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 "rs_refresh_rate_dfx.h"
17
18 #include <parameters.h>
19
20 #include "rs_trace.h"
21 #include "hgm_core.h"
22 #include "pipeline/hardware_thread/rs_realtime_refresh_rate_manager.h"
23 #include "pipeline/render_thread/rs_uni_render_util.h"
24
25 namespace OHOS::Rosen {
26
OnDraw(RSPaintFilterCanvas & canvas)27 void RSRefreshRateDfx::OnDraw(RSPaintFilterCanvas& canvas)
28 {
29 RS_TRACE_FUNC();
30 if (!RSRealtimeRefreshRateManager::Instance().GetShowRefreshRateEnabled()) {
31 return;
32 }
33 auto params = static_cast<RSLogicalDisplayRenderParams*>(logicalDisplayParams_.get());
34 if (UNLIKELY(!params)) {
35 return;
36 }
37 auto screenId = params->GetScreenId();
38 static const std::string FOLD_SCREEN_TYPE = system::GetParameter("const.window.foldscreen.type", "0,0,0,0");
39 const char dualDisplay = '2';
40 // fold device with two logic screens
41 if ((FOLD_SCREEN_TYPE[0] == dualDisplay) && screenId != 0) {
42 return;
43 }
44 uint32_t currentRefreshRate = OHOS::Rosen::HgmCore::Instance().GetScreenCurrentRefreshRate(screenId);
45 uint32_t realtimeRefreshRate = RSRealtimeRefreshRateManager::Instance().GetRealtimeRefreshRate(screenId);
46 static bool showRealtimeRefreshRate = RSSystemProperties::GetVersionType() == "beta";
47 std::string info = std::to_string(currentRefreshRate);
48 if (showRealtimeRefreshRate || RSSystemParameters::GetShowRefreshRateEnabled()) {
49 info += " " + std::to_string(realtimeRefreshRate);
50 }
51 std::shared_ptr<Drawing::Typeface> tf = Drawing::Typeface::MakeFromName("HarmonyOS Sans SC", Drawing::FontStyle());
52 Drawing::Font font;
53 font.SetSize(100); // 100:Scalar of setting font size
54 font.SetTypeface(tf);
55 std::shared_ptr<Drawing::TextBlob> textBlob = Drawing::TextBlob::MakeFromString(info.c_str(), font);
56
57 Drawing::Brush brush;
58 brush.SetColor(currentRefreshRate <= 60 ? SK_ColorRED : SK_ColorGREEN); // low refresh rate 60
59 brush.SetAntiAlias(true);
60 RSAutoCanvasRestore acr(&canvas);
61 canvas.AttachBrush(brush);
62 if (!RefreshRateRotationProcess(canvas, params->GetScreenRotation(),
63 params->GetBounds().GetWidth(), params->GetBounds().GetHeight())) {
64 return;
65 }
66 // 100.f:Scalar x of drawing TextBlob; 200.f:Scalar y of drawing TextBlob
67 canvas.DrawTextBlob(textBlob.get(), 100.f, 200.f);
68 canvas.DetachBrush();
69 }
70
RefreshRateRotationProcess(RSPaintFilterCanvas & canvas,ScreenRotation rotation,float translateWidth,float translateHeight)71 bool RSRefreshRateDfx::RefreshRateRotationProcess(RSPaintFilterCanvas& canvas,
72 ScreenRotation rotation, float translateWidth, float translateHeight)
73 {
74 auto params = static_cast<RSLogicalDisplayRenderParams*>(logicalDisplayParams_.get());
75 auto screenManager = CreateOrGetScreenManager();
76 if (UNLIKELY(params == nullptr || screenManager == nullptr)) {
77 return false;
78 }
79 Drawing::Matrix invertMatrix;
80 if (params->GetMatrix().Invert(invertMatrix)) {
81 canvas.ConcatMatrix(invertMatrix);
82 }
83
84 auto screenId = params->GetScreenId();
85 auto screenCorrection = screenManager->GetScreenCorrection(screenId);
86 if (screenCorrection != ScreenRotation::INVALID_SCREEN_ROTATION &&
87 screenCorrection != ScreenRotation::ROTATION_0) {
88 // Recaculate rotation if mirrored screen has additional rotation angle
89 rotation = static_cast<ScreenRotation>((static_cast<int>(rotation) + SCREEN_ROTATION_NUM
90 - static_cast<int>(screenCorrection)) % SCREEN_ROTATION_NUM);
91 }
92
93 // 2: if ret is odd, width and height should be swapped
94 if ((static_cast<int32_t>(rotation) - static_cast<int32_t>(params->GetNodeRotation())) % 2) {
95 std::swap(translateWidth, translateHeight);
96 }
97
98 canvas.Translate(params->GetOffsetX(), params->GetOffsetY());
99 if (rotation != ScreenRotation::ROTATION_0) {
100 if (rotation == ScreenRotation::ROTATION_90) {
101 canvas.Rotate(-90, 0, 0); // 90 degree for text draw
102 canvas.Translate(-translateWidth, 0);
103 } else if (rotation == ScreenRotation::ROTATION_180) {
104 // 180: degree for text draw, 2: half
105 canvas.Rotate(-180, translateWidth / 2, translateHeight / 2);
106 } else if (rotation == ScreenRotation::ROTATION_270) {
107 canvas.Rotate(-270, 0, 0); // 270 degree for text draw
108 canvas.Translate(0, -translateHeight);
109 } else {
110 return false;
111 }
112 }
113 return true;
114 }
115 } // namespace OHOS::Rosen
116