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