• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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