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 <cstdint>
17 #include <sys/types.h>
18 #include <parameters.h>
19 
20 #include "rs_dirty_rects_dfx.h"
21 #include "rs_trace.h"
22 
23 #include "drawable/rs_render_node_drawable.h"
24 #include "drawable/rs_surface_render_node_drawable.h"
25 #include "params/rs_display_render_params.h"
26 #include "params/rs_surface_render_params.h"
27 #include "platform/common/rs_log.h"
28 #include "screen_manager/rs_screen_manager.h"
29 
30 // fresh rate
31 #include "hgm_core.h"
32 
33 #include "pipeline/rs_realtime_refresh_rate_manager.h"
34 
35 namespace OHOS::Rosen {
36 namespace {
37 // DFX drawing alpha
38 constexpr float DFXFillAlpha = 0.2f;
39 constexpr float DFXFontSize = 24.f;
40 }
41 
42 static const std::map<DirtyRegionType, std::string> DIRTY_REGION_TYPE_MAP {
43     { DirtyRegionType::UPDATE_DIRTY_REGION, "UPDATE_DIRTY_REGION" },
44     { DirtyRegionType::OVERLAY_RECT, "OVERLAY_RECT" },
45     { DirtyRegionType::FILTER_RECT, "FILTER_RECT" },
46     { DirtyRegionType::SHADOW_RECT, "SHADOW_RECT" },
47     { DirtyRegionType::PREPARE_CLIP_RECT, "PREPARE_CLIP_RECT" },
48     { DirtyRegionType::REMOVE_CHILD_RECT, "REMOVE_CHILD_RECT" },
49     { DirtyRegionType::RENDER_PROPERTIES_RECT, "RENDER_PROPERTIES_RECT" },
50     { DirtyRegionType::CANVAS_NODE_SKIP_RECT, "CANVAS_NODE_SKIP_RECT" },
51     { DirtyRegionType::OUTLINE_RECT, "OUTLINE_RECT" },
52     { DirtyRegionType::SUBTREE_SKIP_OUT_OF_PARENT_RECT, "SUBTREE_SKIP_OUT_OF_PARENT_RECT" },
53 };
54 
OnDraw(RSPaintFilterCanvas & canvas)55 void RSDirtyRectsDfx::OnDraw(RSPaintFilterCanvas& canvas)
56 {
57     auto& renderThreadParams = RSUniRenderThread::Instance().GetRSRenderThreadParams();
58     if (UNLIKELY(!renderThreadParams)) {
59         RS_LOGE("RSDirtyRectsDfx::OnDraw render thread params is nullptr!");
60         return;
61     }
62 
63     // the following code makes DirtyRegion visible, enable this method by turning on the dirtyregiondebug property
64     if (renderThreadParams->isPartialRenderEnabled_) {
65         if (renderThreadParams->isDirtyRegionDfxEnabled_) {
66             DrawAllSurfaceDirtyRegionForDFX(canvas);
67         }
68         if (renderThreadParams->isTargetDirtyRegionDfxEnabled_) {
69             DrawTargetSurfaceDirtyRegionForDFX(canvas);
70         }
71         if (renderThreadParams->isDisplayDirtyDfxEnabled_) {
72             DrawDirtyRegionForDFX(canvas, targetDrawable_.GetSyncDirtyManager()->GetMergedDirtyRegions());
73         }
74     }
75 
76     if (renderThreadParams->isOpaqueRegionDfxEnabled_) {
77         DrawAllSurfaceOpaqueRegionForDFX(canvas);
78     }
79     if (renderThreadParams->isVisibleRegionDfxEnabled_) {
80         DrawTargetSurfaceVisibleRegionForDFX(canvas);
81     }
82 
83     if (RSRealtimeRefreshRateManager::Instance().GetShowRefreshRateEnabled()) {
84         DrawCurrentRefreshRate(canvas);
85     }
86 
87     DrawableV2::RSRenderNodeDrawable::DrawDfxForCacheInfo(canvas);
88 }
89 
OnDrawVirtual(RSPaintFilterCanvas & canvas)90 void RSDirtyRectsDfx::OnDrawVirtual(RSPaintFilterCanvas& canvas)
91 {
92     auto& renderThreadParams = RSUniRenderThread::Instance().GetRSRenderThreadParams();
93     if (UNLIKELY(!renderThreadParams)) {
94         RS_LOGE("RSDirtyRectsDfx::OnDraw render thread params is nullptr!");
95         return;
96     }
97 
98     if (renderThreadParams->isVirtualDirtyDfxEnabled_) {
99         DrawDirtyRegionInVirtual(canvas);
100     }
101 }
102 
DrawDirtyRegionInVirtual(RSPaintFilterCanvas & canvas) const103 void RSDirtyRectsDfx::DrawDirtyRegionInVirtual(RSPaintFilterCanvas& canvas) const
104 {
105     for (const auto& subRect : virtualDirtyRects_) {
106         RectI tmpRect;
107 #ifdef RS_ENABLE_VK
108         if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
109             RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
110             tmpRect = subRect;
111         } else {
112             tmpRect = RectI(subRect.GetLeft(),
113                 static_cast<int32_t>(screenInfo_.GetRotatedHeight()) - subRect.GetTop() - subRect.GetHeight(),
114                 subRect.GetWidth(), subRect.GetHeight());
115         }
116 #else
117         tmpRect = RectI(subRect.GetLeft(),
118             static_cast<int32_t>(screenInfo_.GetRotatedHeight()) - subRect.GetTop() - subRect.GetHeight(),
119             subRect.GetWidth(), subRect.GetHeight());
120 #endif
121         DrawDirtyRectForDFX(canvas, tmpRect, Drawing::Color::COLOR_BLUE, RSPaintStyle::STROKE);
122     }
123 }
124 
RefreshRateRotationProcess(RSPaintFilterCanvas & canvas,ScreenRotation rotation,uint64_t screenId)125 bool RSDirtyRectsDfx::RefreshRateRotationProcess(RSPaintFilterCanvas& canvas,
126     ScreenRotation rotation, uint64_t screenId)
127 {
128     if (rotation != ScreenRotation::ROTATION_0) {
129         auto screenManager = CreateOrGetScreenManager();
130         auto mainScreenInfo = screenManager->QueryScreenInfo(screenId);
131         if (rotation == ScreenRotation::ROTATION_90) {
132             canvas.Rotate(-90, 0, 0); // 90 degree for text draw
133             canvas.Translate(-(static_cast<float>(mainScreenInfo.height)), 0);
134         } else if (rotation == ScreenRotation::ROTATION_180) {
135             // 180 degree for text draw
136             canvas.Rotate(-180, static_cast<float>(mainScreenInfo.width) / 2, // 2 half of screen width
137                 static_cast<float>(mainScreenInfo.height) / 2);                 // 2 half of screen height
138         } else if (rotation == ScreenRotation::ROTATION_270) {
139             canvas.Rotate(-270, 0, 0); // 270 degree for text draw
140             canvas.Translate(0, -(static_cast<float>(mainScreenInfo.width)));
141         } else {
142             return false;
143         }
144     }
145     return true;
146 }
147 
DrawCurrentRefreshRate(RSPaintFilterCanvas & canvas)148 void RSDirtyRectsDfx::DrawCurrentRefreshRate(RSPaintFilterCanvas& canvas)
149 {
150     RS_TRACE_FUNC();
151     if (UNLIKELY(!displayParams_)) {
152         return;
153     }
154     auto screenId = displayParams_->GetScreenId();
155     static const std::string FOLD_SCREEN_TYPE = system::GetParameter("const.window.foldscreen.type", "0,0,0,0");
156     const char dualDisplay = '2';
157     // fold device with two logic screens
158     if (FOLD_SCREEN_TYPE[0] == dualDisplay && screenId != 0) {
159         return;
160     }
161     uint32_t currentRefreshRate = OHOS::Rosen::HgmCore::Instance().GetScreenCurrentRefreshRate(screenId);
162     uint32_t realtimeRefreshRate = RSRealtimeRefreshRateManager::Instance().GetRealtimeRefreshRate();
163     if (realtimeRefreshRate > currentRefreshRate) {
164         realtimeRefreshRate = currentRefreshRate;
165     }
166 
167     std::string info = std::to_string(currentRefreshRate) + " " + std::to_string(realtimeRefreshRate);
168     std::shared_ptr<Drawing::Typeface> tf = Drawing::Typeface::MakeFromName("HarmonyOS Sans SC", Drawing::FontStyle());
169     Drawing::Font font;
170     font.SetSize(100); // 100:Scalar of setting font size
171     font.SetTypeface(tf);
172     std::shared_ptr<Drawing::TextBlob> textBlob = Drawing::TextBlob::MakeFromString(info.c_str(), font);
173 
174     Drawing::Brush brush;
175     brush.SetColor(currentRefreshRate <= 60 ? SK_ColorRED : SK_ColorGREEN); // low refresh rate 60
176     brush.SetAntiAlias(true);
177     RSAutoCanvasRestore acr(&canvas);
178     canvas.AttachBrush(brush);
179     auto rotation = displayParams_->GetScreenRotation();
180     // fold device with one logic screen
181     if (RSSystemProperties::IsFoldScreenFlag() && FOLD_SCREEN_TYPE[0] != dualDisplay
182         && screenId == 0) {
183         rotation =
184             (rotation == ScreenRotation::ROTATION_270 ? ScreenRotation::ROTATION_0
185                                                       : static_cast<ScreenRotation>(static_cast<int>(rotation) + 1));
186     }
187     auto saveCount = canvas.Save();
188     if (!RefreshRateRotationProcess(canvas, rotation, screenId)) {
189         return;
190     }
191     // 100.f:Scalar x of drawing TextBlob; 200.f:Scalar y of drawing TextBlob
192     canvas.DrawTextBlob(textBlob.get(), 100.f, 200.f);
193     canvas.RestoreToCount(saveCount);
194     canvas.DetachBrush();
195 }
196 
DrawDirtyRectForDFX(RSPaintFilterCanvas & canvas,RectI dirtyRect,const Drawing::Color color,const RSPaintStyle fillType,int edgeWidth) const197 void RSDirtyRectsDfx::DrawDirtyRectForDFX(RSPaintFilterCanvas& canvas,
198     RectI dirtyRect, const Drawing::Color color, const RSPaintStyle fillType, int edgeWidth) const
199 {
200     if (dirtyRect.width_ <= 0 || dirtyRect.height_ <= 0) {
201         ROSEN_LOGD("DrawDirtyRectForDFX dirty rect is invalid.");
202         return;
203     }
204     ROSEN_LOGD("DrawDirtyRectForDFX current dirtyRect = %{public}s", dirtyRect.ToString().c_str());
205     auto rect = Drawing::Rect(
206         dirtyRect.left_, dirtyRect.top_, dirtyRect.left_ + dirtyRect.width_, dirtyRect.top_ + dirtyRect.height_);
207     RSAutoCanvasRestore acr(&canvas);
208     Drawing::Matrix invertMatrix;
209     if (displayParams_ && displayParams_->GetMatrix().Invert(invertMatrix)) {
210         // Modifying the drawing origin does not affect the actual drawing content
211         canvas.ConcatMatrix(displayParams_->GetMatrix());
212         invertMatrix.MapRect(rect, rect);
213         dirtyRect.SetAll(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
214     }
215     std::string position = std::to_string(dirtyRect.left_) + ',' + std::to_string(dirtyRect.top_) + ',' +
216                            std::to_string(dirtyRect.width_) + ',' + std::to_string(dirtyRect.height_);
217     const int defaultTextOffsetX = edgeWidth;
218     const int defaultTextOffsetY = 30; // text position has 30 pixelSize under the Rect
219     Drawing::Pen rectPen;
220     Drawing::Brush rectBrush;
221     // font size: 24
222     std::shared_ptr<Drawing::TextBlob> textBlob =
223         Drawing::TextBlob::MakeFromString(position.c_str(), Drawing::Font(nullptr, DFXFontSize, 1.0f, 0.0f));
224     if (fillType == RSPaintStyle::STROKE) {
225         rectPen.SetColor(color);
226         rectPen.SetAntiAlias(true);
227         rectPen.SetAlphaF(DFXFillAlpha);
228         rectPen.SetWidth(edgeWidth);
229         rectPen.SetJoinStyle(Drawing::Pen::JoinStyle::ROUND_JOIN);
230         canvas.AttachPen(rectPen);
231     } else {
232         rectBrush.SetColor(color);
233         rectBrush.SetAntiAlias(true);
234         rectBrush.SetAlphaF(DFXFillAlpha);
235         canvas.AttachBrush(rectBrush);
236     }
237     canvas.DrawRect(rect);
238     canvas.DetachPen();
239     canvas.DetachBrush();
240     canvas.AttachBrush(Drawing::Brush());
241     canvas.DrawTextBlob(textBlob.get(), dirtyRect.left_ + defaultTextOffsetX, dirtyRect.top_ + defaultTextOffsetY);
242     canvas.DetachBrush();
243 }
244 
DrawDirtyRegionForDFX(RSPaintFilterCanvas & canvas,const std::vector<RectI> & dirtyRects) const245 void RSDirtyRectsDfx::DrawDirtyRegionForDFX(RSPaintFilterCanvas& canvas, const std::vector<RectI>& dirtyRects) const
246 {
247     for (const auto& subRect : dirtyRects) {
248         DrawDirtyRectForDFX(canvas, subRect, Drawing::Color::COLOR_BLUE, RSPaintStyle::STROKE);
249     }
250 }
251 
DrawAndTraceSingleDirtyRegionTypeForDFX(RSPaintFilterCanvas & canvas,DrawableV2::RSSurfaceRenderNodeDrawable & surfaceDrawable,DirtyRegionType dirtyType,bool isDrawn) const252 void RSDirtyRectsDfx::DrawAndTraceSingleDirtyRegionTypeForDFX(RSPaintFilterCanvas& canvas,
253     DrawableV2::RSSurfaceRenderNodeDrawable& surfaceDrawable, DirtyRegionType dirtyType, bool isDrawn) const
254 {
255     auto dirtyManager = surfaceDrawable.GetSyncDirtyManager();
256     auto matchType = DIRTY_REGION_TYPE_MAP.find(dirtyType);
257     if (matchType == DIRTY_REGION_TYPE_MAP.end()) {
258         return;
259     }
260     std::map<NodeId, RectI> dirtyInfo;
261     std::map<RSRenderNodeType, std::pair<std::string, SkColor>> nodeConfig = {
262         { RSRenderNodeType::CANVAS_NODE, std::make_pair("canvas", SK_ColorRED) },
263         { RSRenderNodeType::SURFACE_NODE, std::make_pair("surface", SK_ColorGREEN) },
264     };
265 
266     std::string subInfo;
267     for (const auto& [nodeType, info] : nodeConfig) {
268         dirtyManager->GetDirtyRegionInfo(dirtyInfo, nodeType, dirtyType);
269         subInfo += (" " + info.first + "node amount: " + std::to_string(dirtyInfo.size()));
270         for (const auto& [nid, rect] : dirtyInfo) {
271             if (isDrawn) {
272                 DrawDirtyRectForDFX(canvas, rect, info.second, RSPaintStyle::STROKE);
273             }
274         }
275     }
276     RS_TRACE_NAME_FMT("DrawAndTraceSingleDirtyRegionTypeForDFX target surface node %s - id[%" PRIu64 "]"
277         " has dirtytype %s %s", surfaceDrawable.GetName().c_str(), surfaceDrawable.GetId(),
278         matchType->second.c_str(), subInfo.c_str());
279     ROSEN_LOGD("DrawAndTraceSingleDirtyRegionTypeForDFX target surface node %{public}s, id[%{public}" PRIu64 "]"
280         "has dirtytype %{public}s%{public}s",
281         surfaceDrawable.GetName().c_str(), surfaceDrawable.GetId(), matchType->second.c_str(), subInfo.c_str());
282 }
283 
DrawDetailedTypesOfDirtyRegionForDFX(RSPaintFilterCanvas & canvas,DrawableV2::RSSurfaceRenderNodeDrawable & surfaceDrawable) const284 bool RSDirtyRectsDfx::DrawDetailedTypesOfDirtyRegionForDFX(RSPaintFilterCanvas& canvas,
285     DrawableV2::RSSurfaceRenderNodeDrawable& surfaceDrawable) const
286 {
287     auto dirtyRegionDebugType = RSUniRenderThread::Instance().GetRSRenderThreadParams()->dirtyRegionDebugType_;
288     if (dirtyRegionDebugType < DirtyRegionDebugType::CUR_DIRTY_DETAIL_ONLY_TRACE) {
289         return false;
290     }
291     if (dirtyRegionDebugType == DirtyRegionDebugType::CUR_DIRTY_DETAIL_ONLY_TRACE) {
292         auto i = DirtyRegionType::UPDATE_DIRTY_REGION;
293         for (; i < DirtyRegionType::TYPE_AMOUNT; i = static_cast<DirtyRegionType>(i + 1)) {
294             DrawAndTraceSingleDirtyRegionTypeForDFX(canvas, surfaceDrawable, i, false);
295         }
296         return true;
297     }
298     static const std::map<DirtyRegionDebugType, DirtyRegionType> DIRTY_REGION_DEBUG_TYPE_MAP {
299         { DirtyRegionDebugType::UPDATE_DIRTY_REGION, DirtyRegionType::UPDATE_DIRTY_REGION },
300         { DirtyRegionDebugType::OVERLAY_RECT, DirtyRegionType::OVERLAY_RECT },
301         { DirtyRegionDebugType::FILTER_RECT, DirtyRegionType::FILTER_RECT },
302         { DirtyRegionDebugType::SHADOW_RECT, DirtyRegionType::SHADOW_RECT },
303         { DirtyRegionDebugType::PREPARE_CLIP_RECT, DirtyRegionType::PREPARE_CLIP_RECT },
304         { DirtyRegionDebugType::REMOVE_CHILD_RECT, DirtyRegionType::REMOVE_CHILD_RECT },
305         { DirtyRegionDebugType::RENDER_PROPERTIES_RECT, DirtyRegionType::RENDER_PROPERTIES_RECT },
306         { DirtyRegionDebugType::CANVAS_NODE_SKIP_RECT, DirtyRegionType::CANVAS_NODE_SKIP_RECT },
307         { DirtyRegionDebugType::OUTLINE_RECT, DirtyRegionType::OUTLINE_RECT },
308         { DirtyRegionDebugType::SUBTREE_SKIP_OUT_OF_PARENT_RECT, DirtyRegionType::SUBTREE_SKIP_OUT_OF_PARENT_RECT },
309     };
310     auto matchType = DIRTY_REGION_DEBUG_TYPE_MAP.find(dirtyRegionDebugType);
311     if (matchType != DIRTY_REGION_DEBUG_TYPE_MAP.end()) {
312         DrawAndTraceSingleDirtyRegionTypeForDFX(canvas, surfaceDrawable, matchType->second);
313     }
314     return true;
315 }
316 
DrawSurfaceOpaqueRegionForDFX(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams) const317 void RSDirtyRectsDfx::DrawSurfaceOpaqueRegionForDFX(RSPaintFilterCanvas& canvas,
318     RSSurfaceRenderParams& surfaceParams) const
319 {
320     const auto& opaqueRegionRects = surfaceParams.GetOpaqueRegion().GetRegionRects();
321     for (const auto& subRect : opaqueRegionRects) {
322         DrawDirtyRectForDFX(canvas, subRect.ToRectI(), Drawing::Color::COLOR_GREEN, RSPaintStyle::FILL, 0);
323     }
324 }
325 
DrawAllSurfaceDirtyRegionForDFX(RSPaintFilterCanvas & canvas) const326 void RSDirtyRectsDfx::DrawAllSurfaceDirtyRegionForDFX(RSPaintFilterCanvas& canvas) const
327 {
328     const auto& visibleDirtyRects = dirtyRegion_.GetRegionRects();
329     std::vector<RectI> rects;
330     for (auto& rect : visibleDirtyRects) {
331         rects.emplace_back(rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_);
332     }
333     DrawDirtyRegionForDFX(canvas, rects);
334 
335     // draw display dirtyregion with red color
336     RectI dirtySurfaceRect = targetDrawable_.GetSyncDirtyManager()->GetDirtyRegion();
337     DrawDirtyRectForDFX(canvas, dirtySurfaceRect, Drawing::Color::COLOR_RED, RSPaintStyle::STROKE);
338 }
339 
DrawAllSurfaceOpaqueRegionForDFX(RSPaintFilterCanvas & canvas) const340 void RSDirtyRectsDfx::DrawAllSurfaceOpaqueRegionForDFX(RSPaintFilterCanvas& canvas) const
341 {
342     if (!displayParams_) {
343         RS_LOGE("RSDirtyRectsDfx::DrawAllSurfaceOpaqueRegionForDFX displayParams is null ptr.");
344         return;
345     }
346     auto& curAllSurfacesDrawables = displayParams_->GetAllMainAndLeashSurfaceDrawables();
347     for (auto it = curAllSurfacesDrawables.rbegin(); it != curAllSurfacesDrawables.rend(); ++it) {
348         auto surfaceParams = static_cast<RSSurfaceRenderParams*>((*it)->GetRenderParams().get());
349         if (surfaceParams && surfaceParams->IsMainWindowType()) {
350             DrawSurfaceOpaqueRegionForDFX(canvas, *surfaceParams);
351         }
352     }
353 }
354 
DrawTargetSurfaceDirtyRegionForDFX(RSPaintFilterCanvas & canvas) const355 void RSDirtyRectsDfx::DrawTargetSurfaceDirtyRegionForDFX(RSPaintFilterCanvas& canvas) const
356 {
357     if (UNLIKELY(!displayParams_)) {
358         return;
359     }
360     const auto& curAllSurfaceDrawables = displayParams_->GetAllMainAndLeashSurfaceDrawables();
361     for (const auto& drawable : curAllSurfaceDrawables) {
362         if (UNLIKELY(!drawable)) {
363             continue;
364         }
365         auto surfaceDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable);
366         auto& surfaceParams = surfaceDrawable->GetRenderParams();
367         if (UNLIKELY(!surfaceParams) || !surfaceParams->IsAppWindow()) {
368             continue;
369         }
370         if (CheckIfSurfaceTargetedForDFX(surfaceDrawable->GetName())) {
371             if (DrawDetailedTypesOfDirtyRegionForDFX(canvas, *surfaceDrawable)) {
372                 continue;
373             }
374             auto dirtyManager = targetDrawable_.GetSyncDirtyManager();
375             const auto& visibleDirtyRects = surfaceDrawable->GetVisibleDirtyRegion().GetRegionRects();
376             std::vector<RectI> rects;
377             for (auto& rect : visibleDirtyRects) {
378                 rects.emplace_back(rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_);
379             }
380             const auto visibleRects = surfaceParams->GetVisibleRegion().GetRegionRects();
381             auto displayDirtyRegion = dirtyManager->GetDirtyRegion();
382             for (auto& rect : visibleRects) {
383                 auto visibleRect = RectI(rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_);
384                 auto intersectRegion = displayDirtyRegion.IntersectRect(visibleRect);
385                 rects.emplace_back(intersectRegion);
386             }
387             DrawDirtyRegionForDFX(canvas, rects);
388         }
389     }
390 }
391 
DrawTargetSurfaceVisibleRegionForDFX(RSPaintFilterCanvas & canvas) const392 void RSDirtyRectsDfx::DrawTargetSurfaceVisibleRegionForDFX(RSPaintFilterCanvas& canvas) const
393 {
394     if (!displayParams_) {
395         RS_LOGE("RSDirtyRectsDfx: displayParams is null ptr.");
396         return;
397     }
398     auto& curAllSurfacesDrawables = displayParams_->GetAllMainAndLeashSurfaceDrawables();
399     for (auto it = curAllSurfacesDrawables.rbegin(); it != curAllSurfacesDrawables.rend(); ++it) {
400         auto surfaceParams = static_cast<RSSurfaceRenderParams*>((*it)->GetRenderParams().get());
401         if (surfaceParams == nullptr || !surfaceParams->IsAppWindow()) {
402             continue;
403         }
404         if (CheckIfSurfaceTargetedForDFX(surfaceParams->GetName())) {
405             const auto visibleRects = surfaceParams->GetVisibleRegion().GetRegionRects();
406             std::vector<RectI> rects;
407             for (auto& rect : visibleRects) {
408                 rects.emplace_back(rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_);
409             }
410             DrawDirtyRegionForDFX(canvas, rects);
411         }
412     }
413 }
414 
415 } // namespace OHOS::Rosen