• 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 "drawable/rs_render_node_drawable.h"
17 #ifdef DDGR_ENABLE_FEATURE_OPINC_DFX
18 #include "string_utils.h"
19 #endif
20 #include "common/rs_optional_trace.h"
21 #include "params/rs_render_params.h"
22 namespace OHOS::Rosen::DrawableV2 {
23 
24 namespace {
25 constexpr int32_t BITMAP_CACHE_SIZE_MIN = 50;
26 constexpr int32_t REALDRAW_WIDTH_EX = 200;
27 constexpr int32_t OPINC_ROOT_TOTAL_MAX = 1;
28 constexpr int32_t OPINC_CACHE_HEIGHT_THRESHOLD = 2720;
29 constexpr int32_t OPINC_CACHE_WIDTH_MAX = 1460;
30 constexpr int32_t OPINC_CACHE_SIZE_MAX = 1314000;
31 }
32 
ShouldPaint() const33 bool RSRenderNodeDrawable::ShouldPaint() const
34 {
35 #ifdef RS_ENABLE_GPU
36     return LIKELY(renderParams_ != nullptr) && renderParams_->GetShouldPaint();
37 #else
38     return false;
39 #endif
40 }
41 
SetAutoCacheEnable(bool autoCacheEnable)42 void RSRenderNodeDrawable::SetAutoCacheEnable(bool autoCacheEnable)
43 {
44     autoCacheEnable_ = autoCacheEnable;
45 }
46 
IsAutoCacheDebugEnable()47 bool RSRenderNodeDrawable::IsAutoCacheDebugEnable()
48 {
49     return RSSystemProperties::GetAutoCacheDebugEnabled() && autoCacheEnable_;
50 }
51 
OpincCalculateBefore(Drawing::Canvas & canvas,const RSRenderParams & params,bool & isOpincDropNodeExt)52 void RSRenderNodeDrawable::OpincCalculateBefore(Drawing::Canvas& canvas,
53     const RSRenderParams& params, bool& isOpincDropNodeExt)
54 {
55 #ifdef RS_ENABLE_GPU
56     isOpincDropNodeExtTemp_ = isOpincDropNodeExt;
57     isOpincCaculateStart_ = false;
58     if (autoCacheEnable_ && IsOpListDrawAreaEnable()) {
59         isOpincCaculateStart_ = canvas.OpCalculateBefore(params.GetMatrix());
60         isOpincDropNodeExt = false;
61     }
62 #endif
63 }
64 
OpincCalculateAfter(Drawing::Canvas & canvas,bool & isOpincDropNodeExt)65 void RSRenderNodeDrawable::OpincCalculateAfter(Drawing::Canvas& canvas, bool& isOpincDropNodeExt)
66 {
67     if (isOpincCaculateStart_) {
68         isOpincCaculateStart_ = false;
69         auto localBound =
70             Drawing::Rect(0.f, 0.f, (float)(OPINC_CACHE_WIDTH_MAX), (float)OPINC_CACHE_HEIGHT_THRESHOLD);
71         auto drawAreaTemp = canvas.OpCalculateAfter(localBound);
72         isDrawAreaEnable_ = DrawAreaEnableState::DRAW_AREA_DISABLE;
73         opCanCache_ = false;
74         if (drawAreaTemp) {
75             opCanCache_ = drawAreaTemp->GetOpInfo().canReUseCache;
76         }
77         if (opCanCache_) {
78             opListDrawAreas_ = std::move(*drawAreaTemp);
79             isDrawAreaEnable_ = DrawAreaEnableState::DRAW_AREA_ENABLE;
80         }
81     }
82     isOpincDropNodeExt = isOpincDropNodeExtTemp_;
83 }
84 
PreDrawableCacheState(RSRenderParams & params,bool & isOpincDropNodeExt)85 bool RSRenderNodeDrawable::PreDrawableCacheState(RSRenderParams& params, bool& isOpincDropNodeExt)
86 {
87 #ifdef RS_ENABLE_GPU
88     if (params.OpincGetCacheChangeState()) {
89         RS_OPTIONAL_TRACE_NAME_FMT("OpincGetCacheChangeState Changed %llx", GetId());
90         DrawableCacheStateReset(params);
91     }
92     return isOpincDropNodeExt && (!IsOpincRootNode());
93 #else
94     return false;
95 #endif
96 }
97 
OpincCanvasUnionTranslate(RSPaintFilterCanvas & canvas)98 void RSRenderNodeDrawable::OpincCanvasUnionTranslate(RSPaintFilterCanvas& canvas)
99 {
100     if (!IsComputeDrawAreaSucc()) {
101         return;
102     }
103     auto& unionRect = GetOpListUnionArea();
104     canvas.Translate(-unionRect.GetLeft(), -unionRect.GetTop());
105 }
106 
ResumeOpincCanvasTranslate(RSPaintFilterCanvas & canvas)107 void RSRenderNodeDrawable::ResumeOpincCanvasTranslate(RSPaintFilterCanvas& canvas)
108 {
109     if (!IsComputeDrawAreaSucc()) {
110         return;
111     }
112     auto& unionRect = GetOpListUnionArea();
113     canvas.Translate(unionRect.GetLeft(), unionRect.GetTop());
114 }
115 
DrawableCacheStateReset(RSRenderParams & params)116 void RSRenderNodeDrawable::DrawableCacheStateReset(RSRenderParams& params)
117 {
118     isDrawAreaEnable_ = DrawAreaEnableState::DRAW_AREA_INIT;
119     rootNodeStragyType_ = NodeStrategyType::CACHE_NONE;
120     temNodeStragyType_ = NodeStrategyType::CACHE_NONE;
121     recordState_ = NodeRecordState::RECORD_NONE;
122     opListDrawAreas_.ResetOpInfo();
123     isOpincRootNode_ = false;
124     opCanCache_ = false;
125     isOpincMarkCached_ = false;
126 }
127 
IsOpListDrawAreaEnable()128 bool RSRenderNodeDrawable::IsOpListDrawAreaEnable()
129 {
130     return (rootNodeStragyType_ == NodeStrategyType::OPINC_AUTOCACHE) &&
131         (recordState_ == NodeRecordState::RECORD_CALCULATE);
132 }
133 
IsTranslate(Drawing::Matrix & mat)134 bool RSRenderNodeDrawable::IsTranslate(Drawing::Matrix& mat)
135 {
136     return (mat.Get(Drawing::Matrix::SCALE_X) == 1.0f) && (mat.Get(Drawing::Matrix::SCALE_Y) == 1.0f) &&
137         (mat.Get(Drawing::Matrix::SKEW_X) == 0.0f) && (mat.Get(Drawing::Matrix::SKEW_Y) == 0.0f);
138 }
139 
NodeCacheStateDisable()140 void RSRenderNodeDrawable::NodeCacheStateDisable()
141 {
142     recordState_ = NodeRecordState::RECORD_DISABLE;
143     rootNodeStragyType_ = NodeStrategyType::CACHE_DISABLE;
144     temNodeStragyType_ = NodeStrategyType::CACHE_DISABLE;
145     isDrawAreaEnable_ = DrawAreaEnableState::DRAW_AREA_DISABLE;
146     if (opCanCache_) {
147         opCanCache_ = false;
148         opListDrawAreas_.ResetOpInfo();
149     }
150 }
151 
BeforeDrawCacheProcessChildNode(NodeStrategyType & cacheStragy,RSRenderParams & params)152 bool RSRenderNodeDrawable::BeforeDrawCacheProcessChildNode(NodeStrategyType& cacheStragy,
153     RSRenderParams& params)
154 {
155 #ifdef RS_ENABLE_GPU
156 #ifdef DDGR_ENABLE_FEATURE_OPINC_DFX
157     RS_TRACE_NAME_FMT("BeforeDrawCacheProcessChildNode cs:%d rs:%d csBak:%d",
158         cacheStragy, recordState_, temNodeStragyType_);
159 #endif
160     // find root node
161     if (cacheStragy != NodeStrategyType::CACHE_NONE || !params.OpincGetRootFlag()) {
162         if (recordState_ == NodeRecordState::RECORD_CACHED &&
163             rootNodeStragyType_ == NodeStrategyType::OPINC_AUTOCACHE) {
164             DrawableCacheStateReset(params);
165         }
166         if (rootNodeStragyType_ == NodeStrategyType::CACHE_DISABLE) {
167             NodeCacheStateDisable();
168         }
169         return false;
170     }
171     return true;
172 #else
173     return false;
174 #endif
175 }
176 
BeforeDrawCacheFindRootNode(Drawing::Canvas & canvas,const RSRenderParams & params,bool & isOpincDropNodeExt)177 void RSRenderNodeDrawable::BeforeDrawCacheFindRootNode(Drawing::Canvas& canvas,
178     const RSRenderParams& params, bool& isOpincDropNodeExt)
179 {
180 #ifdef RS_ENABLE_GPU
181     if (autoCacheEnable_ && !params.OpincGetRootFlag()) {
182         return;
183     }
184     auto size = params.GetCacheSize();
185     if (size.x_ > OPINC_CACHE_WIDTH_MAX || size.y_ > OPINC_CACHE_HEIGHT_THRESHOLD) {
186         RS_TRACE_NAME_FMT("opinc oversize: width:%d, height:%d", size.x_, size.y_);
187         return;
188     }
189     auto isOffscreen = (canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::OFFSCREEN);
190     if (!isOffscreen &&
191         size.y_ > BITMAP_CACHE_SIZE_MIN && size.x_ > BITMAP_CACHE_SIZE_MIN &&
192         size.x_ * size.y_ < OPINC_CACHE_SIZE_MAX) {
193         recordState_ = NodeRecordState::RECORD_CALCULATE;
194         rootNodeStragyType_ = NodeStrategyType::OPINC_AUTOCACHE;
195     }
196 #ifdef DDGR_ENABLE_FEATURE_OPINC_DFX
197     RS_TRACE_NAME_FMT("BeforeDrawCacheFindRootNode rootS:%d xy:%d", rootNodeStragyType_,
198         (size.y_ > BITMAP_CACHE_SIZE_MIN && size.x_ > BITMAP_CACHE_SIZE_MIN));
199 #endif
200 #endif
201 }
202 
BeforeDrawCache(NodeStrategyType & cacheStragy,Drawing::Canvas & canvas,RSRenderParams & params,bool & isOpincDropNodeExt)203 void RSRenderNodeDrawable::BeforeDrawCache(NodeStrategyType& cacheStragy,
204     Drawing::Canvas& canvas, RSRenderParams& params, bool& isOpincDropNodeExt)
205 {
206     if (!autoCacheEnable_) {
207         return;
208     }
209     temNodeStragyType_ = cacheStragy;
210     if (!BeforeDrawCacheProcessChildNode(cacheStragy, params)) {
211         OpincCalculateBefore(canvas, params, isOpincDropNodeExt);
212         return;
213     }
214     switch (recordState_) {
215         case NodeRecordState::RECORD_NONE:
216             // find root node
217             BeforeDrawCacheFindRootNode(canvas, params, isOpincDropNodeExt);
218             break;
219         case NodeRecordState::RECORD_CALCULATE:
220             // cal img
221             break;
222         case NodeRecordState::RECORD_CACHING:
223             // recording
224             break;
225         case NodeRecordState::RECORD_CACHED:
226             reuseCount_++;
227             break;
228         default:
229             break;
230     }
231     cacheStragy = rootNodeStragyType_;
232     OpincCalculateBefore(canvas, params, isOpincDropNodeExt);
233 }
234 
IsOpincNodeInScreenRect(RSRenderParams & params)235 bool RSRenderNodeDrawable::IsOpincNodeInScreenRect(RSRenderParams& params)
236 {
237     auto nodeAbsRect = params.GetAbsDrawRect();
238     RS_OPTIONAL_TRACE_NAME_FMT("opincNodeAbsRect{%d %d %d %d}, screenRect{%d %d %d %d}",
239         nodeAbsRect.GetLeft(), nodeAbsRect.GetTop(), nodeAbsRect.GetRight(), nodeAbsRect.GetBottom(),
240         screenRectInfo_.GetLeft(), screenRectInfo_.GetTop(), screenRectInfo_.GetRight(), screenRectInfo_.GetBottom());
241     if (!nodeAbsRect.IsEmpty() && nodeAbsRect.IsInsideOf(screenRectInfo_)) {
242         return true;
243     }
244     return false;
245 }
246 
AfterDrawCache(NodeStrategyType & cacheStragy,Drawing::Canvas & canvas,RSRenderParams & params,bool & isOpincDropNodeExt,int & opincRootTotalCount)247 void RSRenderNodeDrawable::AfterDrawCache(NodeStrategyType& cacheStragy,
248     Drawing::Canvas& canvas, RSRenderParams& params, bool& isOpincDropNodeExt, int& opincRootTotalCount)
249 {
250     if (!autoCacheEnable_) {
251         return;
252     }
253     OpincCalculateAfter(canvas, isOpincDropNodeExt);
254     if (rootNodeStragyType_ == NodeStrategyType::OPINC_AUTOCACHE && recordState_ == NodeRecordState::RECORD_CALCULATE) {
255         bool isOnlyTranslate = false;
256         auto totalMatrix = canvas.GetTotalMatrix();
257         auto rootAlpha = canvas.GetAlpha();
258         if (IsTranslate(totalMatrix) && (ROSEN_EQ(rootAlpha, 0.0f) || ROSEN_EQ(rootAlpha, 1.0f))) {
259             isOnlyTranslate = true;
260         }
261         if (autoCacheEnable_) {
262             if (isDrawAreaEnable_ == DrawAreaEnableState::DRAW_AREA_ENABLE && isOnlyTranslate) {
263                 recordState_ = NodeRecordState::RECORD_CACHING;
264             } else if (isDrawAreaEnable_ == DrawAreaEnableState::DRAW_AREA_DISABLE) {
265                 NodeCacheStateDisable();
266             }
267         }
268     } else if (rootNodeStragyType_ == NodeStrategyType::OPINC_AUTOCACHE &&
269         recordState_ == NodeRecordState::RECORD_CACHING) {
270         if ((opincRootTotalCount < OPINC_ROOT_TOTAL_MAX) && (!OpincGetCachedMark()) &&
271             IsOpincNodeInScreenRect(params)) {
272             opincRootTotalCount++;
273             isOpincMarkCached_ = true;
274             recordState_ = NodeRecordState::RECORD_CACHED;
275             reuseCount_ = 0;
276             isOpincRootNode_ = true;
277         }
278     }
279     cacheStragy = temNodeStragyType_;
280 }
281 
DrawAutoCache(RSPaintFilterCanvas & canvas,Drawing::Image & image,const Drawing::SamplingOptions & samplingOption,Drawing::SrcRectConstraint constraint)282 bool RSRenderNodeDrawable::DrawAutoCache(RSPaintFilterCanvas& canvas, Drawing::Image& image,
283     const Drawing::SamplingOptions& samplingOption, Drawing::SrcRectConstraint constraint)
284 {
285     if (!IsComputeDrawAreaSucc() || !opCanCache_) {
286         return false;
287     }
288     auto& unionRect = opListDrawAreas_.GetOpInfo().unionRect;
289     auto& drawRects = opListDrawAreas_.GetOpInfo().drawAreaRects;
290     if (unionRect.IsEmpty() || drawRects.size() == 0) {
291         return false;
292     }
293     for (auto& rect : drawRects) {
294         auto srcRect = rect;
295         srcRect.Offset(-unionRect.GetLeft(), -unionRect.GetTop());
296         canvas.DrawImageRect(image, srcRect, rect, samplingOption, constraint);
297     }
298     RS_OPTIONAL_TRACE_NAME_FMT("opinc_size:%d", drawRects.size());
299     return true;
300 }
301 
DrawAutoCacheDfx(RSPaintFilterCanvas & canvas,std::vector<std::pair<RectI,std::string>> & autoCacheRenderNodeInfos)302 void RSRenderNodeDrawable::DrawAutoCacheDfx(RSPaintFilterCanvas& canvas,
303     std::vector<std::pair<RectI, std::string>>& autoCacheRenderNodeInfos)
304 {
305 #ifdef DDGR_ENABLE_FEATURE_OPINC_DFX
306     if (!IsAutoCacheDebugEnable()) {
307         return;
308     }
309     auto& unionRect = opListDrawAreas_.GetOpInfo().unionRect;
310     auto& drawRects = opListDrawAreas_.GetOpInfo().drawAreaRects;
311     if (unionRect.IsEmpty() || drawRects.size() == 0) {
312         return;
313     }
314     Drawing::Brush brush;
315     brush.SetColor(Drawing::Color(0x807C7CD5));
316     canvas.AttachBrush(brush);
317     canvas.DrawRect(unionRect);
318     canvas.DetachBrush();
319     Drawing::Pen pen;
320     pen.SetColor(Drawing::Color(0x80FF00FF));
321     pen.SetWidth(1);
322     canvas.AttachPen(pen);
323     for (auto& rect : drawRects) {
324         canvas.DrawRect(rect);
325     }
326     canvas.DetachPen();
327 #else
328     if (!IsAutoCacheDebugEnable()) {
329         return;
330     }
331     Drawing::Rect dst;
332     canvas.GetTotalMatrix().MapRect(dst, opListDrawAreas_.GetOpInfo().unionRect);
333     RectI dfxRect(static_cast<int>(dst.GetLeft()), static_cast<int>(dst.GetTop()),
334         static_cast<int>(dst.GetWidth()), static_cast<int>(dst.GetHeight()));
335     auto& info = opListDrawAreas_.GetOpInfo();
336     std::string extra =
337         "Re:" + std::to_string(reuseCount_) +
338         " S:" + (rootNodeStragyType_ == NodeStrategyType::OPINC_AUTOCACHE ? "img" : "op") +
339         " Op" + std::to_string(info.num) +
340         " Pe" + std::to_string(info.percent);
341     autoCacheRenderNodeInfos.push_back({dfxRect, extra});
342 #endif
343 }
344 
345 // opinc dfx
GetNodeDebugInfo()346 std::string RSRenderNodeDrawable::GetNodeDebugInfo()
347 {
348     std::string ret("");
349 #ifdef DDGR_ENABLE_FEATURE_OPINC_DFX
350     const auto& params = GetRenderParams();
351     if (!params) {
352         return ret;
353     }
354     auto& unionRect = opListDrawAreas_.GetOpInfo().unionRect;
355     AppendFormat(ret, "%llx, rootF:%d record:%d rootS:%d opCan:%d isRD:%d, GetOpDropped:%d, isOpincDropNodeExt:%d",
356         params->GetId(), params->OpincGetRootFlag(),
357         recordState_, rootNodeStragyType_, opCanCache_, isDrawAreaEnable_, GetOpDropped(), isOpincDropNodeExt_);
358     auto& info = opListDrawAreas_.GetOpInfo();
359     AppendFormat(ret, " opNum%d", info.num, info.percent);
360     auto bounds = params->GetBounds();
361     AppendFormat(ret, ", rr{%.1f %.1f %.1f %.1f}",
362         0.f, 0.f, bounds.GetWidth(), bounds.GetHeight());
363     AppendFormat(ret, ", ur{%.1f %.1f %.1f %.1f}",
364         unionRect.GetLeft(), unionRect.GetTop(), unionRect.GetWidth(), unionRect.GetHeight());
365 #endif
366     return ret;
367 }
368 } // namespace OHOS::Rosen::DrawableV2
369