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