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