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