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