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