1 /*
2 * Copyright (c) 2024 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_anco_manager.h"
17
18 #include <parameters.h>
19 #include "param/sys_param.h"
20 #include "params/rs_surface_render_params.h"
21 #include "platform/common/rs_system_properties.h"
22
23 namespace OHOS::Rosen {
Instance()24 RSAncoManager* RSAncoManager::Instance()
25 {
26 static RSAncoManager instance;
27 return &instance;
28 }
29
AncoDisableHebcProperty()30 static bool AncoDisableHebcProperty()
31 {
32 // Dynamically disable unified rendering layer hebc if persist.sys.graphic.anco.disableHebc equal 1
33 static bool result =
34 std::atoi((system::GetParameter("persist.sys.graphic.anco.disableHebc", "0")).c_str()) != 0;
35 return result;
36 }
37
GetAncoHebcStatus() const38 AncoHebcStatus RSAncoManager::GetAncoHebcStatus() const
39 {
40 if (!AncoDisableHebcProperty()) {
41 return AncoHebcStatus::INITIAL;
42 }
43 return static_cast<AncoHebcStatus>(ancoHebcStatus_.load());
44 }
45
SetAncoHebcStatus(AncoHebcStatus hebcStatus)46 void RSAncoManager::SetAncoHebcStatus(AncoHebcStatus hebcStatus)
47 {
48 ancoHebcStatus_.store(static_cast<int32_t>(hebcStatus));
49 }
50
AncoOptimizeCheck(bool isHebc,int nodesCnt,int sfvNodesCnt)51 bool RSAncoManager::AncoOptimizeCheck(bool isHebc, int nodesCnt, int sfvNodesCnt)
52 {
53 constexpr int minOptimizeAncoNums = 3;
54 constexpr int minOptimizeAncoSfvNums = 2;
55 bool numsMatch = nodesCnt == minOptimizeAncoNums && sfvNodesCnt == minOptimizeAncoSfvNums;
56 if (numsMatch && isHebc) {
57 RS_LOGI("doDirect anco disable hebc");
58 SetAncoHebcStatus(AncoHebcStatus::NOT_USE_HEBC);
59 return true;
60 }
61 if (!numsMatch && !isHebc) {
62 RS_LOGI("doDirect anco enable hebc");
63 SetAncoHebcStatus(AncoHebcStatus::USE_HEBC);
64 return true;
65 }
66 return false;
67 }
68
IsAncoOptimize(ScreenRotation rotation)69 bool RSAncoManager::IsAncoOptimize(ScreenRotation rotation)
70 {
71 if (!AncoDisableHebcProperty() || !RSSurfaceRenderNode::GetOriAncoForceDoDirect() ||
72 rotation != ScreenRotation::ROTATION_0) {
73 return false;
74 }
75 return true;
76 }
77
AncoOptimizeScreenNode(std::shared_ptr<RSSurfaceHandler> & surfaceHandler,std::vector<std::shared_ptr<RSSurfaceRenderNode>> & hardwareEnabledNodes,ScreenRotation rotation,uint32_t width,uint32_t height)78 bool RSAncoManager::AncoOptimizeScreenNode(std::shared_ptr<RSSurfaceHandler>& surfaceHandler,
79 std::vector<std::shared_ptr<RSSurfaceRenderNode>>& hardwareEnabledNodes,
80 ScreenRotation rotation, uint32_t width, uint32_t height)
81 {
82 SetAncoHebcStatus(AncoHebcStatus::INITIAL);
83 if (!IsAncoOptimize(rotation)) {
84 return false;
85 }
86
87 if (surfaceHandler == nullptr || surfaceHandler->GetBuffer() == nullptr) {
88 return false;
89 }
90 bool isHebc = true;
91 if ((surfaceHandler->GetBuffer()->GetUsage() & BUFFER_USAGE_CPU_READ) ||
92 (surfaceHandler->GetBuffer()->GetUsage() & BUFFER_USAGE_CPU_WRITE)) {
93 isHebc = false;
94 }
95
96 // process ScreenNode rect
97 uint32_t minArea = width * height / 2;
98 if (minArea == 0) {
99 return false;
100 }
101
102 int nodesCnt = 0;
103 int sfvNodesCnt = 0;
104 for (auto& surfaceNode : hardwareEnabledNodes) {
105 if ((surfaceNode->GetAncoFlags() & static_cast<uint32_t>(AncoFlags::IS_ANCO_NODE)) == 0) {
106 continue;
107 }
108 auto alpha = surfaceNode->GetGlobalAlpha();
109 if (ROSEN_EQ(alpha, 0.0f) || !surfaceNode->GetRSSurfaceHandler() ||
110 !surfaceNode->GetRSSurfaceHandler()->GetBuffer()) {
111 continue;
112 }
113 #ifdef RS_ENABLE_GPU
114 auto params = static_cast<RSSurfaceRenderParams*>(surfaceNode->GetStagingRenderParams().get());
115 if (params == nullptr) {
116 continue;
117 }
118 auto& layerInfo = params->GetLayerInfo().dstRect;
119 if (layerInfo.w <= 0 || layerInfo.h <= 0) {
120 continue;
121 }
122 if (static_cast<uint32_t>(layerInfo.w * layerInfo.h) >= minArea) {
123 nodesCnt++;
124 if ((surfaceNode->GetAncoFlags() & static_cast<uint32_t>(AncoFlags::ANCO_SFV_NODE)) ==
125 static_cast<uint32_t>(AncoFlags::ANCO_SFV_NODE)) {
126 sfvNodesCnt++;
127 }
128 }
129 #endif
130 }
131
132 return AncoOptimizeCheck(isHebc, nodesCnt, sfvNodesCnt);
133 }
134
UpdateCropRectForAnco(const uint32_t ancoFlags,const Rect & cropRect,const AncoBufferInfo & ancoInfo,Drawing::Rect & outSrcRect)135 void RSAncoManager::UpdateCropRectForAnco(const uint32_t ancoFlags, const Rect& cropRect,
136 const AncoBufferInfo& ancoInfo, Drawing::Rect& outSrcRect)
137 {
138 if (IsAncoSfv(ancoFlags)) {
139 Drawing::Rect srcRect{ cropRect.x, cropRect.y, cropRect.x + cropRect.w, cropRect.y + cropRect.h };
140 outSrcRect.Intersect(srcRect);
141 ShrinkAmountIfNeed(ancoInfo, outSrcRect);
142 }
143 }
144
UpdateCropRectForAnco(const uint32_t ancoFlags,const GraphicIRect & cropRect,const AncoBufferInfo & ancoInfo,Drawing::Rect & outSrcRect)145 void RSAncoManager::UpdateCropRectForAnco(const uint32_t ancoFlags, const GraphicIRect& cropRect,
146 const AncoBufferInfo& ancoInfo, Drawing::Rect& outSrcRect)
147 {
148 // It has already intersected when creating the layer by UpdateLayerSrcRectForAnco function
149 if (IsAncoSfv(ancoFlags)) {
150 outSrcRect = Drawing::Rect(cropRect.x, cropRect.y, cropRect.x + cropRect.w, cropRect.y + cropRect.h);
151 ShrinkAmountIfNeed(ancoInfo, outSrcRect);
152 }
153 }
154
UpdateLayerSrcRectForAnco(const uint32_t ancoFlags,const GraphicIRect & cropRect,GraphicIRect & outSrcRect)155 void RSAncoManager::UpdateLayerSrcRectForAnco(const uint32_t ancoFlags, const GraphicIRect& cropRect,
156 GraphicIRect& outSrcRect)
157 {
158 if (IsAncoSfv(ancoFlags) && ValidCropRect(cropRect)) {
159 IntersectCrop(cropRect, outSrcRect);
160 }
161 }
162
IsAncoSfv(const uint32_t ancoFlags)163 bool RSAncoManager::IsAncoSfv(const uint32_t ancoFlags)
164 {
165 return (ancoFlags & static_cast<uint32_t>(AncoFlags::ANCO_SFV_NODE)) ==
166 static_cast<uint32_t>(AncoFlags::ANCO_SFV_NODE);
167 }
168
ValidCropRect(const GraphicIRect & cropRect)169 bool RSAncoManager::ValidCropRect(const GraphicIRect& cropRect)
170 {
171 if (cropRect.w > 0 && cropRect.h > 0 && cropRect.x >= 0 && cropRect.y >= 0) {
172 return true;
173 }
174 return false;
175 }
176
IntersectCrop(const GraphicIRect & cropRect,GraphicIRect & outSrcRect)177 void RSAncoManager::IntersectCrop(const GraphicIRect& cropRect, GraphicIRect& outSrcRect)
178 {
179 int32_t left = std::max(outSrcRect.x, cropRect.x);
180 int32_t top = std::max(outSrcRect.y, cropRect.y);
181 int32_t right = std::min(outSrcRect.x + outSrcRect.w, cropRect.x + cropRect.w);
182 int32_t bottom = std::min(outSrcRect.y + outSrcRect.h, cropRect.y + cropRect.h);
183 int32_t width = right - left;
184 int32_t height = bottom - top;
185 if (width <= 0 || height <= 0) {
186 return;
187 }
188 outSrcRect = { left, top, width, height };
189 }
190
CalculateShrinkAmount(const int32_t format)191 float RSAncoManager::CalculateShrinkAmount(const int32_t format)
192 {
193 constexpr float GENERALLY_SHRINK_AMOUNT = 0.5f;
194 constexpr float WORST_SHRINK_AMOUNT = 1.0f;
195 switch (format) {
196 case GRAPHIC_PIXEL_FMT_RGBA_8888:
197 case GRAPHIC_PIXEL_FMT_RGBX_8888:
198 case GRAPHIC_PIXEL_FMT_RGBA16_FLOAT:
199 case GRAPHIC_PIXEL_FMT_RGBA_1010102:
200 case GRAPHIC_PIXEL_FMT_RGB_888:
201 case GRAPHIC_PIXEL_FMT_RGB_565:
202 case GRAPHIC_PIXEL_FMT_BGRA_8888:
203 return GENERALLY_SHRINK_AMOUNT;
204 default:
205 return WORST_SHRINK_AMOUNT;
206 }
207 }
208
ShrinkAmountIfNeed(const AncoBufferInfo & ancoInfo,Drawing::Rect & outSrcRect)209 void RSAncoManager::ShrinkAmountIfNeed(const AncoBufferInfo& ancoInfo, Drawing::Rect& outSrcRect)
210 {
211 constexpr float TWOFOLD = 2.0f;
212 float shrinkAmount = CalculateShrinkAmount(ancoInfo.format_);
213 if (outSrcRect.right_ < static_cast<float>(ancoInfo.width_) &&
214 outSrcRect.GetWidth() > TWOFOLD * shrinkAmount) {
215 outSrcRect.left_ += shrinkAmount;
216 outSrcRect.right_ -= shrinkAmount;
217 }
218 if (outSrcRect.bottom_ < static_cast<float>(ancoInfo.height_) &&
219 outSrcRect.GetHeight() > TWOFOLD * shrinkAmount) {
220 outSrcRect.top_ += shrinkAmount;
221 outSrcRect.bottom_ -= shrinkAmount;
222 }
223 }
224 } // namespace OHOS::Rosen
225