1 /*
2 * Copyright (c) 2021-2023 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 "pipeline/rs_render_thread_visitor.h"
17
18 #include <cmath>
19 #ifndef USE_ROSEN_DRAWING
20 #include <include/core/SkColor.h>
21 #include <include/core/SkFont.h>
22 #include <include/core/SkMatrix.h>
23 #include <include/core/SkPaint.h>
24 #include <include/core/SkRect.h>
25 #else
26 #include "draw/color.h"
27 #include "drawing/engine_adapter/impl_interface/matrix_impl.h"
28 #endif
29
30 #include "rs_trace.h"
31
32 #include "command/rs_base_node_command.h"
33 #include "common/rs_obj_abs_geometry.h"
34 #include "common/rs_vector4.h"
35 #include "pipeline/rs_canvas_render_node.h"
36 #include "pipeline/rs_dirty_region_manager.h"
37 #include "pipeline/rs_effect_render_node.h"
38 #include "pipeline/rs_node_map.h"
39 #include "pipeline/rs_proxy_render_node.h"
40 #include "pipeline/rs_render_thread.h"
41 #include "pipeline/rs_root_render_node.h"
42 #include "pipeline/rs_surface_render_node.h"
43 #include "platform/common/rs_log.h"
44 #ifdef NEW_RENDER_CONTEXT
45 #include "rs_render_surface.h"
46 #else
47 #include "platform/drawing/rs_surface.h"
48 #endif
49 #include "transaction/rs_transaction_proxy.h"
50 #include "ui/rs_surface_extractor.h"
51 #include "ui/rs_surface_node.h"
52
53 #ifdef ROSEN_OHOS
54 #include <frame_collector.h>
55 #include <frame_painter.h>
56 #include "platform/ohos/overdraw/rs_cpu_overdraw_canvas_listener.h"
57 #include "platform/ohos/overdraw/rs_gpu_overdraw_canvas_listener.h"
58 #include "platform/ohos/overdraw/rs_overdraw_controller.h"
59 #endif
60
61 namespace OHOS {
62 namespace Rosen {
RSRenderThreadVisitor()63 RSRenderThreadVisitor::RSRenderThreadVisitor()
64 : curDirtyManager_(std::make_shared<RSDirtyRegionManager>()), canvas_(nullptr) {}
65
66 RSRenderThreadVisitor::~RSRenderThreadVisitor() = default;
67
IsValidRootRenderNode(RSRootRenderNode & node)68 bool RSRenderThreadVisitor::IsValidRootRenderNode(RSRootRenderNode& node)
69 {
70 auto ptr = RSNodeMap::Instance().GetNode<RSSurfaceNode>(node.GetRSSurfaceNodeId());
71 if (ptr == nullptr) {
72 ROSEN_LOGE("No valid RSSurfaceNode id");
73 return false;
74 }
75 if (!node.enableRender_) {
76 ROSEN_LOGD("RootNode %s: Invisible", ptr->GetName().c_str());
77 return false;
78 }
79 if (node.GetSuggestedBufferWidth() <= 0 || node.GetSuggestedBufferHeight() <= 0) {
80 ROSEN_LOGD("Root %s: Negative width or height [%f %f]", ptr->GetName().c_str(),
81 node.GetSuggestedBufferWidth(), node.GetSuggestedBufferHeight());
82 return false;
83 }
84 return true;
85 }
86
SetPartialRenderStatus(PartialRenderType status,bool isRenderForced)87 void RSRenderThreadVisitor::SetPartialRenderStatus(PartialRenderType status, bool isRenderForced)
88 {
89 RS_TRACE_FUNC();
90 isRenderForced_ = isRenderForced;
91 dfxDirtyType_ = RSSystemProperties::GetDirtyRegionDebugType();
92 isEglSetDamageRegion_ = !isRenderForced_ && (status != PartialRenderType::DISABLED);
93 isOpDropped_ = (dfxDirtyType_ == DirtyRegionDebugType::DISABLED) && !isRenderForced_ &&
94 (status == PartialRenderType::SET_DAMAGE_AND_DROP_OP);
95 if (partialRenderStatus_ != status) {
96 ROSEN_LOGD("PartialRenderStatus: %d->%d, isRenderForced_=%d, dfxDirtyType_=%d,\
97 isEglSetDamageRegion_=%d, isOpDropped_=%d", partialRenderStatus_, status,
98 isRenderForced_, dfxDirtyType_, isEglSetDamageRegion_, isOpDropped_);
99 }
100 partialRenderStatus_ = status;
101 }
102
PrepareChildren(RSRenderNode & node)103 void RSRenderThreadVisitor::PrepareChildren(RSRenderNode& node)
104 {
105 node.ApplyChildrenModifiers();
106 for (auto& child : node.GetSortedChildren()) {
107 child->Prepare(shared_from_this());
108 }
109 }
110
PrepareRootRenderNode(RSRootRenderNode & node)111 void RSRenderThreadVisitor::PrepareRootRenderNode(RSRootRenderNode& node)
112 {
113 if (isIdle_) {
114 curDirtyManager_ = node.GetDirtyManager();
115 curDirtyManager_->Clear();
116 curDirtyManager_->UpdateDebugRegionTypeEnable(dfxDirtyType_);
117 // After the node calls ApplyModifiers, the modifiers assign the renderProperties to the node
118 // Otherwise node.GetSuggestedBufferHeight always less than 0, causing black screen
119 if (!IsValidRootRenderNode(node)) {
120 return;
121 }
122 dirtyFlag_ = false;
123 isIdle_ = false;
124 PrepareCanvasRenderNode(node);
125 isIdle_ = true;
126 } else {
127 PrepareCanvasRenderNode(node);
128 }
129 }
130
ResetAndPrepareChildrenNode(RSRenderNode & node,std::shared_ptr<RSBaseRenderNode> nodeParent)131 void RSRenderThreadVisitor::ResetAndPrepareChildrenNode(RSRenderNode& node,
132 std::shared_ptr<RSBaseRenderNode> nodeParent)
133 {
134 // merge last childRect as dirty if any child has been removed
135 if (curDirtyManager_ && node.HasRemovedChild()) {
136 curDirtyManager_->MergeDirtyRect(node.GetChildrenRect());
137 node.ResetHasRemovedChild();
138 }
139 // reset childRect before prepare children
140 node.ResetChildrenRect();
141 node.UpdateChildrenOutOfRectFlag(false);
142 PrepareChildren(node);
143 // accumulate direct parent's childrenRect
144 node.UpdateParentChildrenRect(nodeParent);
145 }
146
PrepareCanvasRenderNode(RSCanvasRenderNode & node)147 void RSRenderThreadVisitor::PrepareCanvasRenderNode(RSCanvasRenderNode& node)
148 {
149 if (!node.ShouldPaint() || curDirtyManager_ == nullptr) {
150 return;
151 }
152 bool dirtyFlag = dirtyFlag_;
153 auto nodeParent = node.GetParent().lock();
154 dirtyFlag_ = node.Update(*curDirtyManager_, nodeParent, dirtyFlag_);
155 if (node.IsDirtyRegionUpdated() && curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
156 curDirtyManager_->UpdateDirtyRegionInfoForDfx(node.GetId(), RSRenderNodeType::CANVAS_NODE,
157 DirtyRegionType::UPDATE_DIRTY_REGION, node.GetOldDirty());
158 }
159 ResetAndPrepareChildrenNode(node, nodeParent);
160 node.UpdateEffectRegion(effectRegion_);
161 dirtyFlag_ = dirtyFlag;
162 }
163
PrepareSurfaceRenderNode(RSSurfaceRenderNode & node)164 void RSRenderThreadVisitor::PrepareSurfaceRenderNode(RSSurfaceRenderNode& node)
165 {
166 if (curDirtyManager_ == nullptr) {
167 return;
168 }
169 bool dirtyFlag = dirtyFlag_;
170 auto nodeParent = node.GetParent().lock();
171 // If rt buffer switches to be available
172 // set its SurfaceRenderNode's render dirty
173 if (!node.IsNotifyRTBufferAvailablePre() && node.IsNotifyRTBufferAvailable()) {
174 ROSEN_LOGD("NotifyRTBufferAvailable and set it dirty");
175 node.SetDirty();
176 }
177 dirtyFlag_ = node.Update(*curDirtyManager_, nodeParent, dirtyFlag_);
178 if (node.IsDirtyRegionUpdated() && curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
179 curDirtyManager_->UpdateDirtyRegionInfoForDfx(node.GetId(), RSRenderNodeType::SURFACE_NODE,
180 DirtyRegionType::UPDATE_DIRTY_REGION, node.GetOldDirty());
181 }
182 ResetAndPrepareChildrenNode(node, nodeParent);
183 dirtyFlag_ = dirtyFlag;
184 }
185
PrepareEffectRenderNode(RSEffectRenderNode & node)186 void RSRenderThreadVisitor::PrepareEffectRenderNode(RSEffectRenderNode& node)
187 {
188 if (!node.ShouldPaint() || curDirtyManager_ == nullptr) {
189 return;
190 }
191 auto effectRegion = effectRegion_;
192
193 #ifndef USE_ROSEN_DRAWING
194 effectRegion_ = SkPath();
195 #else
196 effectRegion_ = Drawing::Path();
197 #endif
198 bool dirtyFlag = dirtyFlag_;
199 auto nodeParent = node.GetParent().lock();
200 dirtyFlag_ = node.Update(*curDirtyManager_, nodeParent, dirtyFlag_);
201 ResetAndPrepareChildrenNode(node, nodeParent);
202 node.SetEffectRegion(effectRegion_);
203
204 effectRegion_ = effectRegion;
205 dirtyFlag_ = dirtyFlag;
206 }
207
208 #ifndef USE_ROSEN_DRAWING
DrawRectOnCanvas(const RectI & dirtyRect,const SkColor color,const SkPaint::Style fillType,float alpha,int strokeWidth)209 void RSRenderThreadVisitor::DrawRectOnCanvas(const RectI& dirtyRect, const SkColor color,
210 const SkPaint::Style fillType, float alpha, int strokeWidth)
211 #else
212 void RSRenderThreadVisitor::DrawRectOnCanvas(const RectI& dirtyRect, const Drawing::ColorQuad color,
213 RSPaintStyle fillType, float alpha, int strokeWidth)
214 #endif // USE_ROSEN_DRAWING
215 {
216 if (dirtyRect.IsEmpty()) {
217 ROSEN_LOGD("DrawRectOnCanvas dirty rect is invalid.");
218 return;
219 }
220 #ifndef USE_ROSEN_DRAWING
221 auto skRect = SkRect::MakeXYWH(dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
222 SkPaint rectPaint;
223 rectPaint.setColor(color);
224 rectPaint.setAntiAlias(true);
225 rectPaint.setAlphaf(alpha);
226 rectPaint.setStyle(fillType);
227 rectPaint.setStrokeWidth(strokeWidth);
228 if (fillType == SkPaint::kFill_Style) {
229 rectPaint.setStrokeJoin(SkPaint::kRound_Join);
230 }
231 canvas_->drawRect(skRect, rectPaint);
232 #else
233 auto drawingRect = Drawing::Rect(dirtyRect.left_, dirtyRect.top_,
234 dirtyRect.width_ + dirtyRect.left_, dirtyRect.height_ + dirtyRect.top_);
235 Drawing::Pen pen;
236 Drawing::Brush brush;
237 if (fillType == RSPaintStyle::STROKE) {
238 pen.SetColor(color);
239 pen.SetAntiAlias(true);
240 pen.SetAlphaF(alpha);
241 pen.SetWidth(strokeWidth);
242 pen.SetJoinStyle(Drawing::Pen::JoinStyle::ROUND_JOIN);
243 canvas_->AttachPen(pen);
244 } else if (fillType == RSPaintStyle::FILL) {
245 brush.SetColor(color);
246 brush.SetAntiAlias(true);
247 brush.SetAlphaF(alpha);
248 canvas_->AttachBrush(brush);
249 }
250 canvas_->DrawRect(drawingRect);
251 canvas_->DetachPen();
252 canvas_->DetachBrush();
253 #endif // USE_ROSEN_DRAWING
254 }
255
DrawDirtyRegion()256 void RSRenderThreadVisitor::DrawDirtyRegion()
257 {
258 auto dirtyRect = RectI();
259 const float fillAlpha = 0.2;
260 const float edgeAlpha = 0.4;
261
262 if (curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::MULTI_HISTORY)) {
263 dirtyRect = curDirtyManager_->GetDirtyRegion();
264 if (dirtyRect.IsEmpty()) {
265 ROSEN_LOGD("DrawDirtyRegion his dirty rect is invalid. dirtyRect = %s", dirtyRect.ToString().c_str());
266 } else {
267 ROSEN_LOGD("DrawDirtyRegion his dirty rect. dirtyRect = %s", dirtyRect.ToString().c_str());
268 // green
269 #ifndef USE_ROSEN_DRAWING
270 DrawRectOnCanvas(dirtyRect, 0x442FDD2F, SkPaint::kFill_Style, fillAlpha);
271 DrawRectOnCanvas(dirtyRect, 0xFF2FDD2F, SkPaint::kStroke_Style, edgeAlpha);
272 #else
273 DrawRectOnCanvas(dirtyRect, 0x442FDD2F, RSPaintStyle::FILL, fillAlpha);
274 DrawRectOnCanvas(dirtyRect, 0xFF2FDD2F, RSPaintStyle::STROKE, edgeAlpha);
275 #endif // USE_ROSEN_DRAWING
276 }
277 }
278
279 if (curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_WHOLE)) {
280 dirtyRect = curDirtyManager_->GetLatestDirtyRegion();
281 if (dirtyRect.IsEmpty()) {
282 ROSEN_LOGD("DrawDirtyRegion current frame's dirty rect is invalid. dirtyRect = %s",
283 dirtyRect.ToString().c_str());
284 } else {
285 ROSEN_LOGD("DrawDirtyRegion cur dirty rect. dirtyRect = %s", dirtyRect.ToString().c_str());
286 // yellow
287 #ifndef USE_ROSEN_DRAWING
288 DrawRectOnCanvas(dirtyRect, 0x88FFFF00, SkPaint::kFill_Style, fillAlpha);
289 DrawRectOnCanvas(dirtyRect, 0xFFFFFF00, SkPaint::kStroke_Style, edgeAlpha);
290 #else
291 DrawRectOnCanvas(dirtyRect, 0x88FFFF00, RSPaintStyle::FILL, fillAlpha);
292 DrawRectOnCanvas(dirtyRect, 0xFFFFFF00, RSPaintStyle::STROKE, edgeAlpha);
293 #endif // USE_ROSEN_DRAWING
294 }
295 }
296
297 if (curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
298 const int strokeWidth = 4;
299 std::map<NodeId, RectI> dirtyRegionRects_;
300 curDirtyManager_->GetDirtyRegionInfo(dirtyRegionRects_, RSRenderNodeType::CANVAS_NODE,
301 DirtyRegionType::UPDATE_DIRTY_REGION);
302 ROSEN_LOGD("DrawDirtyRegion canvas dirtyRegionRects_ size %zu", dirtyRegionRects_.size());
303 // Draw Canvas Node
304 for (const auto& [nid, subRect] : dirtyRegionRects_) {
305 ROSEN_LOGD("DrawDirtyRegion canvas node id %" PRIu64 " is dirty. dirtyRect = %s",
306 nid, subRect.ToString().c_str());
307 #ifndef USE_ROSEN_DRAWING
308 DrawRectOnCanvas(subRect, 0x88FF0000, SkPaint::kStroke_Style, edgeAlpha, strokeWidth);
309 #else
310 DrawRectOnCanvas(subRect, 0x88FF0000, RSPaintStyle::STROKE, edgeAlpha, strokeWidth);
311 #endif // USE_ROSEN_DRAWING
312 }
313
314 curDirtyManager_->GetDirtyRegionInfo(dirtyRegionRects_, RSRenderNodeType::SURFACE_NODE,
315 DirtyRegionType::UPDATE_DIRTY_REGION);
316 ROSEN_LOGD("DrawDirtyRegion surface dirtyRegionRects_ size %zu", dirtyRegionRects_.size());
317 // Draw Surface Node
318 for (const auto& [nid, subRect] : dirtyRegionRects_) {
319 ROSEN_LOGD("DrawDirtyRegion surface node id %" PRIu64 " is dirty. dirtyRect = %s",
320 nid, subRect.ToString().c_str());
321 #ifndef USE_ROSEN_DRAWING
322 DrawRectOnCanvas(subRect, 0xFFD864D8, SkPaint::kStroke_Style, edgeAlpha, strokeWidth);
323 #else
324 DrawRectOnCanvas(subRect, 0xFFD864D8, RSPaintStyle::STROKE, edgeAlpha, strokeWidth);
325 #endif // USE_ROSEN_DRAWING
326 }
327 }
328 }
329
330 #ifdef NEW_RENDER_CONTEXT
UpdateDirtyAndSetEGLDamageRegion(std::shared_ptr<RSRenderSurface> & surface)331 void RSRenderThreadVisitor::UpdateDirtyAndSetEGLDamageRegion(std::shared_ptr<RSRenderSurface>& surface)
332 #else
333 void RSRenderThreadVisitor::UpdateDirtyAndSetEGLDamageRegion(std::unique_ptr<RSSurfaceFrame>& surfaceFrame)
334 #endif
335 {
336 RS_TRACE_BEGIN("UpdateDirtyAndSetEGLDamageRegion");
337 #ifdef RS_ENABLE_EGLQUERYSURFACE
338 if (isEglSetDamageRegion_) {
339 // get and update valid buffer age(>0) to merge history
340 #if defined(NEW_RENDER_CONTEXT)
341 if (surface == nullptr) {
342 ROSEN_LOGE("Failed to UpdateDirtyAndSetEGLDamageRegion, surface is nullptr");
343 return;
344 }
345 int32_t bufferAge = surface->GetBufferAge();
346 #else
347 int32_t bufferAge = surfaceFrame->GetBufferAge();
348 #endif
349 if (!curDirtyManager_->SetBufferAge(bufferAge)) {
350 ROSEN_LOGD("ProcessRootRenderNode SetBufferAge with invalid buffer age %d", bufferAge);
351 curDirtyManager_->ResetDirtyAsSurfaceSize();
352 }
353 curDirtyManager_->UpdateDirtyByAligned();
354 curDirtyManager_->UpdateDirty();
355 curDirtyRegion_ = curDirtyManager_->GetDirtyRegion();
356 // only set damage region if dirty region and buffer age is valid(>0)
357 if (bufferAge >= 0) {
358 // get dirty rect coordinated from upper left to lower left corner in current surface
359 RectI dirtyRectFlip = curDirtyManager_->GetRectFlipWithinSurface(curDirtyRegion_);
360 // set dirty rect as eglSurfaceFrame's damage region
361 #if defined(NEW_RENDER_CONTEXT)
362 std::vector<RectI> dirtyRects;
363 dirtyRects.push_back(dirtyRectFlip);
364 surface->SetDamageRegion(dirtyRects);
365 #else
366 surfaceFrame->SetDamageRegion(dirtyRectFlip.left_, dirtyRectFlip.top_, dirtyRectFlip.width_,
367 dirtyRectFlip.height_);
368 #endif
369 // flip aligned rect for op drops
370 curDirtyRegion_ = curDirtyManager_->GetRectFlipWithinSurface(dirtyRectFlip);
371 ROSEN_LOGD("GetPartialRenderEnabled buffer age %d, dirtyRectFlip = [%d, %d, %d, %d], "
372 "dirtyRectAlign = [%d, %d, %d, %d]", bufferAge,
373 dirtyRectFlip.left_, dirtyRectFlip.top_, dirtyRectFlip.width_, dirtyRectFlip.height_,
374 curDirtyRegion_.left_, curDirtyRegion_.top_, curDirtyRegion_.width_, curDirtyRegion_.height_);
375 }
376 } else {
377 curDirtyManager_->UpdateDirty();
378 curDirtyRegion_ = curDirtyManager_->GetDirtyRegion();
379 }
380 #else
381 curDirtyManager_->UpdateDirty();
382 curDirtyRegion_ = curDirtyManager_->GetDirtyRegion();
383 #endif
384 ROSEN_LOGD("UpdateDirtyAndSetEGLDamageRegion dirtyRect = [%d, %d, %d, %d]",
385 curDirtyRegion_.left_, curDirtyRegion_.top_, curDirtyRegion_.width_, curDirtyRegion_.height_);
386 RS_TRACE_END();
387 }
388
ProcessChildren(RSRenderNode & node)389 void RSRenderThreadVisitor::ProcessChildren(RSRenderNode& node)
390 {
391 for (auto& child : node.GetSortedChildren()) {
392 child->Process(shared_from_this());
393 }
394 }
395
ProcessRootRenderNode(RSRootRenderNode & node)396 void RSRenderThreadVisitor::ProcessRootRenderNode(RSRootRenderNode& node)
397 {
398 if (!isIdle_) {
399 ProcessCanvasRenderNode(node);
400 return;
401 }
402 auto ptr = RSNodeMap::Instance().GetNode<RSSurfaceNode>(node.GetRSSurfaceNodeId());
403 if (!IsValidRootRenderNode(node)) {
404 return;
405 }
406
407 curDirtyManager_ = node.GetDirtyManager();
408
409 #ifndef ROSEN_CROSS_PLATFORM
410 auto surfaceNodeColorSpace = ptr->GetColorSpace();
411 #endif
412 #ifdef NEW_RENDER_CONTEXT
413 std::shared_ptr<RSRenderSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(ptr);
414 #else
415 std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(ptr);
416 #endif
417 if (rsSurface == nullptr) {
418 ROSEN_LOGE("ProcessRoot %s: No RSSurface found", ptr->GetName().c_str());
419 return;
420 }
421 // Update queue size for each process loop in case it dynamically changes
422 queueSize_ = rsSurface->GetQueueSize();
423
424 #ifndef ROSEN_CROSS_PLATFORM
425 auto rsSurfaceColorSpace = rsSurface->GetColorSpace();
426 if (surfaceNodeColorSpace != rsSurfaceColorSpace) {
427 ROSEN_LOGD("Set new colorspace %d to rsSurface", surfaceNodeColorSpace);
428 rsSurface->SetColorSpace(surfaceNodeColorSpace);
429 }
430 #endif
431
432 #if defined(ACE_ENABLE_GL)
433 #if defined(NEW_RENDER_CONTEXT)
434 std::shared_ptr<RenderContextBase> rc = RSRenderThread::Instance().GetRenderContext();
435 std::shared_ptr<DrawingContext> dc = RSRenderThread::Instance().GetDrawingContext();
436 rsSurface->SetDrawingContext(dc);
437 #else
438 RenderContext* rc = RSRenderThread::Instance().GetRenderContext();
439 #endif
440 rsSurface->SetRenderContext(rc);
441 #endif
442 uiTimestamp_ = RSRenderThread::Instance().GetUITimestamp();
443 RS_TRACE_BEGIN(ptr->GetName() + " rsSurface->RequestFrame");
444 #ifdef ROSEN_OHOS
445 FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::ReleaseStart);
446 #endif
447
448 const auto& property = node.GetRenderProperties();
449 const float bufferWidth = node.GetSuggestedBufferWidth() * property.GetScaleX();
450 const float bufferHeight = node.GetSuggestedBufferHeight() * property.GetScaleY();
451 #ifdef ROSEN_OHOS
452 auto surfaceFrame = rsSurface->RequestFrame(bufferWidth, bufferHeight, uiTimestamp_);
453 #else
454 auto surfaceFrame = rsSurface->RequestFrame(std::round(bufferWidth), std::round(bufferHeight), uiTimestamp_);
455 #endif
456 RS_TRACE_END();
457 if (surfaceFrame == nullptr) {
458 ROSEN_LOGI("ProcessRoot %s: Request Frame Failed", ptr->GetName().c_str());
459 #ifdef ROSEN_OHOS
460 FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::ReleaseEnd);
461 #endif
462 return;
463 }
464 #ifndef USE_ROSEN_DRAWING
465 #ifdef NEW_RENDER_CONTEXT
466 auto skSurface = rsSurface->GetSurface();
467 #else
468 auto skSurface = surfaceFrame->GetSurface();
469 #endif
470 if (skSurface == nullptr) {
471 ROSEN_LOGE("skSurface null.");
472 return;
473 }
474 if (skSurface->getCanvas() == nullptr) {
475 ROSEN_LOGE("skSurface.getCanvas is null.");
476 return;
477 }
478 #else
479 auto surface = surfaceFrame->GetSurface();
480 if (surface == nullptr) {
481 ROSEN_LOGE("surface null.");
482 return;
483 }
484 if (surface->GetCanvas() == nullptr) {
485 ROSEN_LOGE("surface.GetCanvas is null.");
486 return;
487 }
488 #endif
489
490 #ifdef ROSEN_OHOS
491 // if listenedCanvas is nullptr, that means disabled or listen failed
492 std::shared_ptr<RSListenedCanvas> listenedCanvas = nullptr;
493 std::shared_ptr<RSCanvasListener> overdrawListener = nullptr;
494
495 if (RSOverdrawController::GetInstance().IsEnabled()) {
496 auto &oc = RSOverdrawController::GetInstance();
497 #ifndef USE_ROSEN_DRAWING
498 listenedCanvas = std::make_shared<RSListenedCanvas>(skSurface.get());
499 #else
500 listenedCanvas = std::make_shared<RSListenedCanvas>(*surface);
501 #endif
502 overdrawListener = oc.CreateListener<RSCPUOverdrawCanvasListener>(listenedCanvas.get());
503 if (overdrawListener == nullptr) {
504 overdrawListener = oc.CreateListener<RSGPUOverdrawCanvasListener>(listenedCanvas.get());
505 }
506
507 if (overdrawListener != nullptr) {
508 listenedCanvas->SetListener(overdrawListener);
509 } else {
510 // create listener failed
511 listenedCanvas = nullptr;
512 }
513 }
514
515 if (listenedCanvas != nullptr) {
516 canvas_ = listenedCanvas;
517 } else {
518 #ifndef USE_ROSEN_DRAWING
519 canvas_ = std::make_shared<RSPaintFilterCanvas>(skSurface.get());
520 #else
521 canvas_ = std::make_shared<RSPaintFilterCanvas>(surface.get());
522 #endif // USE_ROSEN_DRAWING
523 }
524 #else
525 #ifndef USE_ROSEN_DRAWING
526 canvas_ = std::make_shared<RSPaintFilterCanvas>(skSurface.get());
527 #else
528 canvas_ = std::make_shared<RSPaintFilterCanvas>(surface.get());
529 #endif // USE_ROSEN_DRAWING
530 #endif
531
532 canvas_->SetHighContrast(RSRenderThread::Instance().isHighContrastEnabled());
533
534 // node's surface size already check, so here we do not need to check return
535 // attention: currently surfaceW/H are float values transformed into int implicitly
536 (void)curDirtyManager_->SetSurfaceSize(bufferWidth, bufferHeight);
537 // keep non-negative rect region within surface
538 curDirtyManager_->ClipDirtyRectWithinSurface();
539 // reset matrix
540 const float rootWidth = property.GetFrameWidth() * property.GetScaleX();
541 const float rootHeight = property.GetFrameHeight() * property.GetScaleY();
542 #ifndef USE_ROSEN_DRAWING
543 SkMatrix gravityMatrix;
544 #else
545 Drawing::Matrix gravityMatrix;
546 #endif // USE_ROSEN_DRAWING
547 (void)RSPropertiesPainter::GetGravityMatrix(
548 Gravity::RESIZE, RectF { 0.0f, 0.0f, bufferWidth, bufferHeight }, rootWidth, rootHeight, gravityMatrix);
549
550 if (isRenderForced_ ||
551 curDirtyManager_->GetCurrentFrameDirtyRegion().GetWidth() == 0 ||
552 curDirtyManager_->GetCurrentFrameDirtyRegion().GetHeight() == 0 ||
553 #ifndef USE_ROSEN_DRAWING
554 !gravityMatrix.isIdentity()) {
555 #else
556 !(gravityMatrix == Drawing::Matrix())) {
557 #endif // USE_ROSEN_DRAWING
558 curDirtyManager_->ResetDirtyAsSurfaceSize();
559 }
560 #ifdef NEW_RENDER_CONTEXT
561 UpdateDirtyAndSetEGLDamageRegion(rsSurface);
562 #else
563 UpdateDirtyAndSetEGLDamageRegion(surfaceFrame);
564 #endif
565
566 #ifndef USE_ROSEN_DRAWING
567 canvas_->clipRect(SkRect::MakeWH(bufferWidth, bufferHeight));
568 canvas_->clear(SK_ColorTRANSPARENT);
569 #else
570 canvas_->ClipRect(Drawing::Rect(0, 0, bufferWidth, bufferHeight), Drawing::ClipOp::INTERSECT, false);
571 canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
572 #endif // USE_ROSEN_DRAWING
573 isIdle_ = false;
574
575 // clear current children before traversal, we will re-add them again during traversal
576 childSurfaceNodeIds_.clear();
577
578 #ifndef USE_ROSEN_DRAWING
579 canvas_->concat(gravityMatrix);
580 #else
581 canvas_->ConcatMatrix(gravityMatrix);
582 #endif // USE_ROSEN_DRAWING
583 parentSurfaceNodeMatrix_ = gravityMatrix;
584
585 RS_TRACE_BEGIN("ProcessRenderNodes");
586 ProcessCanvasRenderNode(node);
587
588 if (childSurfaceNodeIds_ != node.childSurfaceNodeIds_) {
589 auto thisSurfaceNodeId = node.GetRSSurfaceNodeId();
590 std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeClearChild>(thisSurfaceNodeId);
591 SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_TO_SELF);
592 for (const auto& childSurfaceNodeId : childSurfaceNodeIds_) {
593 command = std::make_unique<RSBaseNodeAddChild>(thisSurfaceNodeId, childSurfaceNodeId, -1);
594 SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_TO_SELF);
595 }
596 node.childSurfaceNodeIds_ = std::move(childSurfaceNodeIds_);
597 }
598 RS_TRACE_END();
599
600 auto transactionProxy = RSTransactionProxy::GetInstance();
601 if (transactionProxy != nullptr) {
602 ROSEN_LOGD("RSRenderThreadVisitor FlushImplicitTransactionFromRT uiTimestamp = %" PRIu64, uiTimestamp_);
603 transactionProxy->FlushImplicitTransactionFromRT(uiTimestamp_);
604 }
605
606 if ((dfxDirtyType_ != DirtyRegionDebugType::DISABLED) && curDirtyManager_->IsDirty()) {
607 ROSEN_LOGD("ProcessRootRenderNode %s [%" PRIu64 "] draw dirtyRect", ptr->GetName().c_str(), node.GetId());
608 DrawDirtyRegion();
609 }
610
611 #ifdef ROSEN_OHOS
612 if (overdrawListener != nullptr) {
613 overdrawListener->Draw();
614 }
615
616 FramePainter fpainter(FrameCollector::GetInstance());
617 fpainter.Draw(*canvas_);
618 FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::ReleaseEnd);
619 FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::FlushStart);
620 #endif
621
622 RS_TRACE_BEGIN(ptr->GetName() + " rsSurface->FlushFrame");
623 ROSEN_LOGD("RSRenderThreadVisitor FlushFrame surfaceNodeId = %" PRIu64 ", uiTimestamp = %" PRIu64,
624 node.GetRSSurfaceNodeId(), uiTimestamp_);
625 #ifdef NEW_RENDER_CONTEXT
626 rsSurface->FlushFrame(uiTimestamp_);
627 #else
628 rsSurface->FlushFrame(surfaceFrame, uiTimestamp_);
629 #endif
630 #ifdef ROSEN_OHOS
631 FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::FlushEnd);
632 #endif
633 RS_TRACE_END();
634
635 canvas_ = nullptr;
636 isIdle_ = true;
637 }
638
639 void RSRenderThreadVisitor::ProcessCanvasRenderNode(RSCanvasRenderNode& node)
640 {
641 if (!node.ShouldPaint()) {
642 return;
643 }
644 if (!canvas_) {
645 ROSEN_LOGE("RSRenderThreadVisitor::ProcessCanvasRenderNode, canvas is nullptr");
646 return;
647 }
648 #ifdef RS_ENABLE_EGLQUERYSURFACE
649 node.UpdateRenderStatus(curDirtyRegion_, isOpDropped_);
650 if (node.IsRenderUpdateIgnored()) {
651 return;
652 }
653 #endif
654 const auto& property = node.GetRenderProperties();
655 if (property.IsSpherizeValid()) {
656 if (node.GetCacheType() != CacheType::ANIMATE_PROPERTY) {
657 node.SetCacheType(CacheType::ANIMATE_PROPERTY);
658 node.ClearCacheSurface();
659 }
660 if (!node.GetCompletedCacheSurface() && UpdateAnimatePropertyCacheSurface(node)) {
661 node.UpdateCompletedCacheSurface();
662 }
663 node.ProcessTransitionBeforeChildren(*canvas_);
664 RSPropertiesPainter::DrawSpherize(
665 property, *canvas_, node.GetCompletedCacheSurface());
666 node.ProcessTransitionAfterChildren(*canvas_);
667 return;
668 }
669
670 if (node.GetCompletedCacheSurface()) {
671 node.SetCacheType(CacheType::NONE);
672 node.ClearCacheSurface();
673 }
674 node.ProcessRenderBeforeChildren(*canvas_);
675 node.ProcessRenderContents(*canvas_);
676 ProcessChildren(node);
677 node.ProcessRenderAfterChildren(*canvas_);
678 }
679
680 bool RSRenderThreadVisitor::UpdateAnimatePropertyCacheSurface(RSRenderNode& node)
681 {
682 if (!node.GetCacheSurface()) {
683 #ifndef USE_ROSEN_DRAWING
684 #ifdef NEW_SKIA
685 node.InitCacheSurface(canvas_ ? canvas_->recordingContext() : nullptr);
686 #else
687 node.InitCacheSurface(canvas_ ? canvas_->getGrContext() : nullptr);
688 #endif
689 #else
690 node.InitCacheSurface(canvas_ ? canvas_->GetGPUContext().get() : nullptr);
691 #endif
692 }
693 if (!node.GetCacheSurface()) {
694 return false;
695 }
696 auto cacheCanvas = std::make_shared<RSPaintFilterCanvas>(node.GetCacheSurface().get());
697 if (!cacheCanvas) {
698 return false;
699 }
700
701 // copy current canvas properties into cacheCanvas
702 cacheCanvas->CopyConfiguration(*canvas_);
703
704 // When drawing CacheSurface, all child node should be drawn.
705 // So set isOpDropped_ = false here.
706 bool isOpDropped = isOpDropped_;
707 isOpDropped_ = false;
708
709 swap(cacheCanvas, canvas_);
710 node.ProcessAnimatePropertyBeforeChildren(*canvas_);
711 node.ProcessRenderContents(*canvas_);
712 ProcessChildren(node);
713 node.ProcessAnimatePropertyAfterChildren(*canvas_);
714 swap(cacheCanvas, canvas_);
715
716 isOpDropped_ = isOpDropped;
717 return true;
718 }
719
720 void RSRenderThreadVisitor::ProcessEffectRenderNode(RSEffectRenderNode& node)
721 {
722 if (!node.ShouldPaint()) {
723 RS_LOGD("RSRenderThreadVisitor::ProcessEffectRenderNode, no need process");
724 return;
725 }
726 if (!canvas_) {
727 RS_LOGE("RSRenderThreadVisitor::ProcessEffectRenderNode, canvas is nullptr");
728 return;
729 }
730 node.ProcessRenderBeforeChildren(*canvas_);
731 ProcessChildren(node);
732 node.ProcessRenderAfterChildren(*canvas_);
733 }
734
735 void RSRenderThreadVisitor::ProcessSurfaceRenderNode(RSSurfaceRenderNode& node)
736 {
737 if (!canvas_) {
738 ROSEN_LOGE("RSRenderThreadVisitor::ProcessSurfaceRenderNode, canvas is nullptr");
739 return;
740 }
741 if (!node.ShouldPaint()) {
742 ROSEN_LOGI("RSRenderThreadVisitor::ProcessSurfaceRenderNode node : %" PRIu64 " is invisible", node.GetId());
743 node.SetContextAlpha(0.0f);
744 return;
745 }
746 // RSSurfaceRenderNode in RSRenderThreadVisitor do not have information of property.
747 // We only get parent's matrix and send it to RenderService
748 #ifndef USE_ROSEN_DRAWING
749 SkMatrix invertMatrix;
750 SkMatrix contextMatrix = canvas_->getTotalMatrix();
751
752 if (parentSurfaceNodeMatrix_.invert(&invertMatrix)) {
753 contextMatrix.preConcat(invertMatrix);
754 #else
755 Drawing::Matrix invertMatrix;
756 Drawing::Matrix contextMatrix = canvas_->GetTotalMatrix();
757
758 if (parentSurfaceNodeMatrix_.Invert(invertMatrix)) {
759 contextMatrix.PreConcat(invertMatrix);
760 #endif // USE_ROSEN_DRAWING
761 } else {
762 ROSEN_LOGE("RSRenderThreadVisitor::ProcessSurfaceRenderNode, invertMatrix failed");
763 }
764 node.SetContextMatrix(contextMatrix);
765 node.SetContextAlpha(canvas_->GetAlpha());
766
767 // PLANNING: This is a temporary modification. Animation for surfaceView should not be triggered in RenderService.
768 // We plan to refactor code here.
769 node.SetContextBounds(node.GetRenderProperties().GetBounds());
770
771 auto clipRect = RSPaintFilterCanvas::GetLocalClipBounds(*canvas_);
772 #ifndef USE_ROSEN_DRAWING
773 if (!clipRect.has_value() ||
774 clipRect->width() < std::numeric_limits<float>::epsilon() ||
775 clipRect->height() < std::numeric_limits<float>::epsilon()) {
776 #else
777 if (!clipRect.has_value() ||
778 clipRect->GetWidth() < std::numeric_limits<float>::epsilon() ||
779 clipRect->GetHeight() < std::numeric_limits<float>::epsilon()) {
780 #endif
781 // if clipRect is empty, this node will be removed from parent's children list.
782 node.SetContextClipRegion(std::nullopt);
783
784 static int pixel = 1;
785 auto width = std::floor(node.GetRenderProperties().GetBoundsWidth() - (2 * pixel)); // width decrease 2 pixels
786 auto height = std::floor(node.GetRenderProperties().GetBoundsHeight() - (2 * pixel)); // height decrease 2 pixels
787 auto iter = surfaceCallbacks_.find(node.GetId());
788 if (iter != surfaceCallbacks_.end()) {
789 (iter->second)(canvas_->getTotalMatrix().getTranslateX(), canvas_->getTotalMatrix().getTranslateY(), width, height);
790 }
791 return;
792 }
793 node.SetContextClipRegion(clipRect);
794
795 // clip hole
796 ClipHoleForSurfaceNode(node);
797
798 // 1. add this node to parent's children list
799 childSurfaceNodeIds_.emplace_back(node.GetId());
800
801 // 2. backup and reset environment variables before traversal children
802 std::vector<NodeId> siblingSurfaceNodeIds(std::move(childSurfaceNodeIds_));
803 childSurfaceNodeIds_.clear();
804 auto parentSurfaceNodeMatrix = parentSurfaceNodeMatrix_;
805 #ifndef USE_ROSEN_DRAWING
806 parentSurfaceNodeMatrix_ = canvas_->getTotalMatrix();
807 #else
808 parentSurfaceNodeMatrix_ = canvas_->GetTotalMatrix();
809 #endif // USE_ROSEN_DRAWING
810
811 // 3. traversal children, child surface node will be added to childSurfaceNodeIds_
812 // note: apply current node properties onto canvas if there is any child node
813 ProcessChildren(node);
814
815 // 4. if children changed, sync children to RenderService
816 if (childSurfaceNodeIds_ != node.childSurfaceNodeIds_) {
817 auto thisSurfaceNodeId = node.GetId();
818 std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeClearChild>(thisSurfaceNodeId);
819 SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_TO_SELF);
820 for (const auto& childSurfaceNodeId : childSurfaceNodeIds_) {
821 command = std::make_unique<RSBaseNodeAddChild>(thisSurfaceNodeId, childSurfaceNodeId, -1);
822 SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_TO_SELF);
823 }
824 node.childSurfaceNodeIds_ = std::move(childSurfaceNodeIds_);
825 }
826
827 // 5. restore environments variables before continue traversal siblings
828 childSurfaceNodeIds_ = std::move(siblingSurfaceNodeIds);
829 parentSurfaceNodeMatrix_ = parentSurfaceNodeMatrix;
830
831 // 6.draw border
832 #ifndef USE_ROSEN_DRAWING
833 canvas_->save();
834 auto geoPtr = (node.GetRenderProperties().GetBoundsGeometry());
835 canvas_->concat(geoPtr->GetMatrix());
836 RSPropertiesPainter::DrawBorder(node.GetRenderProperties(), *canvas_);
837 canvas_->restore();
838 #else
839 canvas_->Save();
840 auto geoPtr = (node.GetRenderProperties().GetBoundsGeometry());
841 canvas_->ConcatMatrix(geoPtr->GetMatrix());
842 RSPropertiesPainter::DrawBorder(node.GetRenderProperties(), *canvas_);
843 canvas_->Restore();
844 #endif
845 }
846
847 void RSRenderThreadVisitor::ProcessProxyRenderNode(RSProxyRenderNode& node)
848 {
849 if (!canvas_) {
850 ROSEN_LOGE("RSRenderThreadVisitor::ProcessProxyRenderNode, canvas is nullptr");
851 return;
852 }
853 // RSProxyRenderNode in RSRenderThreadVisitor do not have information of property.
854 // We only get parent's matrix and send it to RenderService
855 #ifdef ROSEN_OHOS
856 #ifndef USE_ROSEN_DRAWING
857 SkMatrix invertMatrix;
858 SkMatrix contextMatrix = canvas_->getTotalMatrix();
859 if (parentSurfaceNodeMatrix_.invert(&invertMatrix)) {
860 contextMatrix.preConcat(invertMatrix);
861 } else {
862 ROSEN_LOGE("RSRenderThreadVisitor::ProcessProxyRenderNode, invertMatrix failed");
863 }
864 #else
865 Drawing::Matrix invertMatrix;
866 Drawing::Matrix contextMatrix = canvas_->GetTotalMatrix();
867
868 if (parentSurfaceNodeMatrix_.Invert(invertMatrix)) {
869 contextMatrix.PreConcat(invertMatrix);
870 } else {
871 ROSEN_LOGE("RSRenderThreadVisitor::ProcessProxyRenderNode, invertMatrix failed");
872 }
873 #endif // USE_ROSEN_DRAWING
874 node.SetContextMatrix(contextMatrix);
875 node.SetContextAlpha(canvas_->GetAlpha());
876
877 // context clipRect should be based on parent node's coordinate system, in dividend render mode, it is the
878 // same as canvas coordinate system.
879 auto clipRect = RSPaintFilterCanvas::GetLocalClipBounds(*canvas_);
880 node.SetContextClipRegion(clipRect);
881 #endif
882 }
883
884 void RSRenderThreadVisitor::AddSurfaceChangedCallBack(uint64_t id,
885 const std::function<void(float, float, float, float)>& callback)
886 {
887 surfaceCallbacks_.emplace(id, callback);
888 }
889
890 void RSRenderThreadVisitor::RemoveSurfaceChangedCallBack(uint64_t id)
891 {
892 surfaceCallbacks_.erase(id);
893 }
894
895 void RSRenderThreadVisitor::ClipHoleForSurfaceNode(RSSurfaceRenderNode& node)
896 {
897 // Calculation position in RenderService may appear floating point number, and it will be removed.
898 // It caused missed line problem on surfaceview hap, so we subtract one pixel when cliphole to avoid this problem
899 static int pixel = 1;
900 auto x = std::ceil(node.GetRenderProperties().GetBoundsPositionX() + pixel); // x increase 1 pixel
901 auto y = std::ceil(node.GetRenderProperties().GetBoundsPositionY() + pixel); // y increase 1 pixel
902 auto width = std::floor(node.GetRenderProperties().GetBoundsWidth() - (2 * pixel)); // width decrease 2 pixels
903 auto height = std::floor(node.GetRenderProperties().GetBoundsHeight() - (2 * pixel)); // height decrease 2 pixels
904 #ifndef USE_ROSEN_DRAWING
905 canvas_->save();
906 SkRect originRect = SkRect::MakeXYWH(x, y, width, height);
907 canvas_->clipRect(originRect);
908
909 auto iter = surfaceCallbacks_.find(node.GetId());
910 if (iter != surfaceCallbacks_.end()) {
911 (iter->second)(canvas_->getTotalMatrix().getTranslateX(), canvas_->getTotalMatrix().getTranslateY(), width, height);
912 }
913
914 if (node.IsNotifyRTBufferAvailable()) {
915 ROSEN_LOGD("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %" PRIu64 ", clip [%f, %f, %f, %f]",
916 node.GetId(), x, y, width, height);
917 canvas_->clear(SK_ColorTRANSPARENT);
918 } else {
919 ROSEN_LOGD("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %" PRIu64 ", not clip [%f, %f, %f, %f]",
920 node.GetId(), x, y, width, height);
921 auto backgroundColor = node.GetRenderProperties().GetBackgroundColor();
922 if (backgroundColor != RgbPalette::Transparent()) {
923 canvas_->clear(backgroundColor.AsArgbInt());
924 }
925 }
926 canvas_->restore();
927 #else
928 canvas_->Save();
929 Drawing::Rect originRect = Drawing::Rect(x, y, width + x, height + y);
930 canvas_->ClipRect(originRect, Drawing::ClipOp::INTERSECT, false);
931 if (node.IsNotifyRTBufferAvailable() == true) {
932 ROSEN_LOGI("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %" PRIu64 ", clip [%f, %f, %f, %f]",
933 node.GetId(), x, y, width, height);
934 canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
935 } else {
936 ROSEN_LOGI("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %" PRIu64 ", not clip [%f, %f, %f, %f]",
937 node.GetId(), x, y, width, height);
938 auto backgroundColor = node.GetRenderProperties().GetBackgroundColor();
939 if (backgroundColor != RgbPalette::Transparent()) {
940 canvas_->Clear(backgroundColor.AsArgbInt());
941 }
942 }
943 canvas_->Restore();
944 #endif // USE_ROSEN_DRAWING
945 }
946
947 void RSRenderThreadVisitor::SendCommandFromRT(std::unique_ptr<RSCommand>& command, NodeId nodeId, FollowType followType)
948 {
949 auto transactionProxy = RSTransactionProxy::GetInstance();
950 if (transactionProxy != nullptr) {
951 transactionProxy->AddCommandFromRT(command, nodeId, followType);
952 }
953 }
954 } // namespace Rosen
955 } // namespace OHOS
956