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