1 /*
2 * Copyright (c) 2024 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 "drawable/rs_surface_render_node_drawable.h"
17
18 #include "acquire_fence_manager.h"
19 #include "impl_interface/region_impl.h"
20 #include "rs_trace.h"
21 #include "common/rs_color.h"
22 #include "common/rs_common_def.h"
23 #include "common/rs_optional_trace.h"
24 #include "common/rs_obj_abs_geometry.h"
25 #include "draw/brush.h"
26 #include "drawable/rs_display_render_node_drawable.h"
27 #include "memory/rs_tag_tracker.h"
28 #include "params/rs_display_render_params.h"
29 #include "params/rs_surface_render_params.h"
30 #include "pipeline/rs_paint_filter_canvas.h"
31 #include "pipeline/rs_surface_handler.h"
32 #include "pipeline/rs_surface_render_node.h"
33 #include "pipeline/rs_uni_render_thread.h"
34 #include "pipeline/rs_uni_render_util.h"
35 #ifdef OHOS_BUILD_ENABLE_MAGICCURSOR
36 #include "pipeline/pointer_render/rs_pointer_render_manager.h"
37 #endif
38
39 #include "platform/common/rs_log.h"
40 #include "platform/ohos/rs_node_stats.h"
41 #include "utils/rect.h"
42 #include "utils/region.h"
43
44 #include "pipeline/rs_uifirst_manager.h"
45 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
46 #include "pipeline/rs_main_thread.h"
47 #ifdef RS_ENABLE_VK
48 #include "include/gpu/GrBackendSurface.h"
49 #include "platform/ohos/backend/native_buffer_utils.h"
50 #include "platform/ohos/backend/rs_vulkan_context.h"
51 #endif
52
53 #include "luminance/rs_luminance_control.h"
54 #ifdef USE_VIDEO_PROCESSING_ENGINE
55 #include "metadata_helper.h"
56 #endif
57 namespace {
58 constexpr int32_t CORNER_SIZE = 4;
59 constexpr float GAMMA2_2 = 2.2f;
60 }
61 namespace OHOS::Rosen::DrawableV2 {
62 RSSurfaceRenderNodeDrawable::Registrar RSSurfaceRenderNodeDrawable::instance_;
63
RSSurfaceRenderNodeDrawable(std::shared_ptr<const RSRenderNode> && node)64 RSSurfaceRenderNodeDrawable::RSSurfaceRenderNodeDrawable(std::shared_ptr<const RSRenderNode>&& node)
65 : RSRenderNodeDrawable(std::move(node)), syncDirtyManager_(std::make_shared<RSDirtyRegionManager>())
66 {
67 auto nodeSp = std::const_pointer_cast<RSRenderNode>(node);
68 auto surfaceNode = std::static_pointer_cast<RSSurfaceRenderNode>(nodeSp);
69 name_ = surfaceNode->GetName();
70 surfaceNodeType_ = surfaceNode->GetSurfaceNodeType();
71 #ifndef ROSEN_CROSS_PLATFORM
72 consumerOnDraw_ = surfaceNode->GetRSSurfaceHandler()->GetConsumer();
73 #endif
74 surfaceHandlerUiFirst_ = std::make_shared<RSSurfaceHandler>(nodeId_);
75 }
76
~RSSurfaceRenderNodeDrawable()77 RSSurfaceRenderNodeDrawable::~RSSurfaceRenderNodeDrawable()
78 {
79 ClearCacheSurfaceInThread();
80 }
81
OnGenerate(std::shared_ptr<const RSRenderNode> node)82 RSRenderNodeDrawable::Ptr RSSurfaceRenderNodeDrawable::OnGenerate(std::shared_ptr<const RSRenderNode> node)
83 {
84 RS_TRACE_NAME("RSRenderNodeDrawable::Ptr RSSurfaceRenderNodeDrawable::OnGenerate");
85 return new RSSurfaceRenderNodeDrawable(std::move(node));
86 }
87
OnGeneralProcess(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams,bool isSelfDrawingSurface)88 void RSSurfaceRenderNodeDrawable::OnGeneralProcess(
89 RSPaintFilterCanvas& canvas, RSSurfaceRenderParams& surfaceParams, bool isSelfDrawingSurface)
90 {
91 auto bounds = surfaceParams.GetFrameRect();
92
93 // 1. draw background
94 DrawBackground(canvas, bounds);
95
96 // 2. draw self drawing node
97 if (surfaceParams.GetBuffer() != nullptr) {
98 DealWithSelfDrawingNodeBuffer(canvas, surfaceParams);
99 }
100
101 if (isSelfDrawingSurface) {
102 canvas.Restore();
103 }
104
105 // 3. Draw content of this node by the main canvas.
106 DrawContent(canvas, bounds);
107
108 // 4. Draw children of this node by the main canvas.
109 DrawChildren(canvas, bounds);
110
111 // 5. Draw foreground of this node by the main canvas.
112 DrawForeground(canvas, bounds);
113 }
114
CalculateVisibleRegion(RSRenderThreadParams & uniParam,RSSurfaceRenderParams & surfaceParams,RSSurfaceRenderNodeDrawable & surfaceDrawable,bool isOffscreen) const115 Drawing::Region RSSurfaceRenderNodeDrawable::CalculateVisibleRegion(RSRenderThreadParams& uniParam,
116 RSSurfaceRenderParams& surfaceParams, RSSurfaceRenderNodeDrawable& surfaceDrawable, bool isOffscreen) const
117 {
118 Drawing::Region resultRegion;
119 if (!surfaceParams.IsMainWindowType()) {
120 return resultRegion;
121 }
122
123 // FUTURE: return real region
124 if (isOffscreen) {
125 resultRegion.SetRect(Drawing::RectI(0, 0,
126 DRAWING_MAX_S32_FITS_IN_FLOAT, DRAWING_MAX_S32_FITS_IN_FLOAT));
127 return resultRegion;
128 }
129
130 auto visibleRegion = surfaceParams.GetVisibleRegion();
131 if (uniParam.IsOcclusionEnabled() && visibleRegion.IsEmpty()) {
132 return resultRegion;
133 }
134 // The region is dirty region of this SurfaceNode.
135 Occlusion::Region surfaceNodeDirtyRegion(GetSyncDirtyManager()->GetDirtyRegion());
136 // The region is the result of global dirty region AND occlusion region.
137 Occlusion::Region globalDirtyRegion = GetGlobalDirtyRegion();
138 // This include dirty region and occlusion region when surfaceNode is mainWindow.
139 auto dirtyRegion = globalDirtyRegion.Or(surfaceNodeDirtyRegion);
140 auto visibleDirtyRegion = dirtyRegion.And(visibleRegion);
141 if (visibleDirtyRegion.IsEmpty()) {
142 RS_LOGD("RSSurfaceRenderNodeDrawable::OnDraw occlusion skip SurfaceName:%s NodeId:%" PRIu64 "",
143 surfaceDrawable.GetName().c_str(), surfaceParams.GetId());
144 return resultRegion;
145 }
146
147 for (auto& rect : visibleDirtyRegion.GetRegionRects()) {
148 Drawing::Region tempRegion;
149 tempRegion.SetRect(Drawing::RectI(rect.left_, rect.top_, rect.right_, rect.bottom_));
150 resultRegion.Op(tempRegion, Drawing::RegionOp::UNION);
151 }
152 return resultRegion;
153 }
154
155 // To be deleted after captureWindow being deleted
CheckIfNeedResetRotate(RSPaintFilterCanvas & canvas)156 bool RSSurfaceRenderNodeDrawable::CheckIfNeedResetRotate(RSPaintFilterCanvas& canvas)
157 {
158 auto matrix = canvas.GetTotalMatrix();
159 int angle = RSUniRenderUtil::GetRotationFromMatrix(matrix);
160 constexpr int ROTATION_90 = 90;
161 return angle != 0 && angle % ROTATION_90 == 0;
162 }
163
164 // To be deleted after captureWindow being deleted
FindInstanceChildOfDisplay(std::shared_ptr<RSRenderNode> node)165 NodeId RSSurfaceRenderNodeDrawable::FindInstanceChildOfDisplay(std::shared_ptr<RSRenderNode> node)
166 {
167 if (node == nullptr || node->GetParent().lock() == nullptr) {
168 return INVALID_NODEID;
169 } else if (node->GetParent().lock()->GetType() == RSRenderNodeType::DISPLAY_NODE) {
170 return node->GetId();
171 } else {
172 return FindInstanceChildOfDisplay(node->GetParent().lock());
173 }
174 }
175
176 // To be deleted after captureWindow being deleted
CacheImgForCapture(RSPaintFilterCanvas & canvas,RSDisplayRenderNodeDrawable & curDisplayNodeDrawable)177 void RSSurfaceRenderNodeDrawable::CacheImgForCapture(RSPaintFilterCanvas& canvas,
178 RSDisplayRenderNodeDrawable& curDisplayNodeDrawable)
179 {
180 auto& params = curDisplayNodeDrawable.GetRenderParams();
181 if (!params->GetSecurityDisplay() && canvas.GetSurface() != nullptr) {
182 bool resetRotate = CheckIfNeedResetRotate(canvas);
183 auto cacheImgForCapture = canvas.GetSurface()->GetImageSnapshot();
184 auto& mirroredNodeDrawable =
185 params->GetMirrorSourceDrawable().lock()
186 ? static_cast<RSDisplayRenderNodeDrawable&>(*(params->GetMirrorSourceDrawable().lock()))
187 : curDisplayNodeDrawable;
188 mirroredNodeDrawable.SetCacheImgForCapture(cacheImgForCapture);
189 mirroredNodeDrawable.SetResetRotate(resetRotate);
190 }
191 }
192
PrepareOffscreenRender()193 bool RSSurfaceRenderNodeDrawable::PrepareOffscreenRender()
194 {
195 // cleanup
196 canvasBackup_ = nullptr;
197
198 // check offscreen size
199 if (curCanvas_->GetSurface() == nullptr) {
200 RS_LOGE("RSSurfaceRenderNodeDrawable::PrepareOffscreenRender, current surface is nullptr");
201 return false;
202 }
203 int offscreenWidth = curCanvas_->GetSurface()->Width();
204 int offscreenHeight = curCanvas_->GetSurface()->Height();
205 if (offscreenWidth <= 0 || offscreenHeight <= 0) {
206 RS_LOGE("RSSurfaceRenderNodeDrawable::PrepareOffscreenRender, offscreenWidth or offscreenHeight is invalid");
207 return false;
208 }
209
210 int maxRenderSize = std::max(offscreenWidth, offscreenHeight);
211 // create offscreen surface and canvas
212 if (offscreenSurface_ == nullptr || maxRenderSize_ != maxRenderSize) {
213 RS_LOGD("PrepareOffscreenRender create offscreen surface offscreenSurface_,\
214 new [%{public}d, %{public}d %{public}d]", offscreenWidth, offscreenHeight, maxRenderSize);
215 RS_TRACE_NAME_FMT("PrepareOffscreenRender surface size: [%d, %d]", maxRenderSize, maxRenderSize);
216 maxRenderSize_ = maxRenderSize;
217 offscreenSurface_ = curCanvas_->GetSurface()->MakeSurface(maxRenderSize_, maxRenderSize_);
218 }
219 if (offscreenSurface_ == nullptr) {
220 RS_LOGE("RSSurfaceRenderNodeDrawable::PrepareOffscreenRender, offscreenSurface is nullptr");
221 return false;
222 }
223
224 offscreenCanvas_ = std::make_shared<RSPaintFilterCanvas>(offscreenSurface_.get());
225
226 // copy HDR properties into offscreen canvas
227 offscreenCanvas_->CopyHDRConfiguration(*curCanvas_);
228 // copy current canvas properties into offscreen canvas
229 offscreenCanvas_->CopyConfigurationToOffscreenCanvas(*curCanvas_);
230
231 // backup current canvas and replace with offscreen canvas
232 canvasBackup_ = curCanvas_;
233 curCanvas_ = offscreenCanvas_.get();
234 curCanvas_->SetDisableFilterCache(true);
235 arc_ = std::make_unique<RSAutoCanvasRestore>(curCanvas_, RSPaintFilterCanvas::SaveType::kCanvasAndAlpha);
236 curCanvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
237 return true;
238 }
239
FinishOffscreenRender(const Drawing::SamplingOptions & sampling)240 void RSSurfaceRenderNodeDrawable::FinishOffscreenRender(const Drawing::SamplingOptions& sampling)
241 {
242 if (canvasBackup_ == nullptr) {
243 RS_LOGE("RSSurfaceRenderNodeDrawable::FinishOffscreenRender, canvasBackup_ is nullptr");
244 return;
245 }
246 if (offscreenSurface_ == nullptr) {
247 RS_LOGE("RSSurfaceRenderNodeDrawable::FinishOffscreenRender, offscreenSurface_ is nullptr");
248 return;
249 }
250 auto image = offscreenSurface_->GetImageSnapshot();
251 if (image == nullptr) {
252 RS_LOGE("RSSurfaceRenderNodeDrawable::FinishOffscreenRender, Surface::GetImageSnapshot is nullptr");
253 return;
254 }
255 // draw offscreen surface to current canvas
256 Drawing::Brush paint;
257 paint.SetAntiAlias(true);
258 canvasBackup_->AttachBrush(paint);
259 canvasBackup_->DrawImage(*image, 0, 0, sampling);
260 canvasBackup_->DetachBrush();
261 arc_ = nullptr;
262 curCanvas_ = canvasBackup_;
263 }
264
IsHardwareEnabled()265 bool RSSurfaceRenderNodeDrawable::IsHardwareEnabled()
266 {
267 auto& hardwareDrawables =
268 RSUniRenderThread::Instance().GetRSRenderThreadParams()->GetHardwareEnabledTypeDrawables();
269 for (const auto& drawable : hardwareDrawables) {
270 if (!drawable || !drawable->GetRenderParams()) {
271 continue;
272 }
273 auto params = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
274 if (!params || !params->GetHardwareEnabled()) {
275 continue;
276 }
277 return true;
278 }
279 return false;
280 }
281
OnDraw(Drawing::Canvas & canvas)282 void RSSurfaceRenderNodeDrawable::OnDraw(Drawing::Canvas& canvas)
283 {
284 SetDrawSkipType(DrawSkipType::NONE);
285 if (!ShouldPaint()) {
286 SetDrawSkipType(DrawSkipType::SHOULD_NOT_PAINT);
287 RS_TRACE_NAME_FMT("RSSurfaceRenderNodeDrawable::OnDraw %s should not paint", name_.c_str());
288 return;
289 }
290
291 auto rscanvas = reinterpret_cast<RSPaintFilterCanvas*>(&canvas);
292 if (!rscanvas) {
293 SetDrawSkipType(DrawSkipType::CANVAS_NULL);
294 RS_LOGE("RSSurfaceRenderNodeDrawable::OnDraw, rscanvas us nullptr");
295 return;
296 }
297 auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
298 if (UNLIKELY(!uniParam)) {
299 SetDrawSkipType(DrawSkipType::RENDER_THREAD_PARAMS_NULL);
300 RS_LOGE("RSSurfaceRenderNodeDrawable::OnDraw uniParam is nullptr");
301 return;
302 }
303 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(GetRenderParams().get());
304 if (!surfaceParams) {
305 SetDrawSkipType(DrawSkipType::RENDER_PARAMS_NULL);
306 RS_LOGE("RSSurfaceRenderNodeDrawable::OnDraw params is nullptr");
307 return;
308 }
309 if (surfaceParams->GetSkipDraw()) {
310 SetDrawSkipType(DrawSkipType::SURFACE_PARAMS_SKIP_DRAW);
311 RS_TRACE_NAME_FMT("RSSurfaceRenderNodeDrawable::OnDraw SkipDraw [%s] Id:%llu",
312 name_.c_str(), surfaceParams->GetId());
313 return;
314 }
315 auto renderEngine_ = RSUniRenderThread::Instance().GetRenderEngine();
316 auto unmappedCache = surfaceParams->GetBufferClearCacheSet();
317 if (unmappedCache.size() > 0) {
318 // remove imagecahce when its bufferQueue gobackground
319 renderEngine_->ClearCacheSet(unmappedCache);
320 }
321 if (autoCacheEnable_) {
322 nodeCacheType_ = NodeStrategyType::CACHE_NONE;
323 }
324 bool isUiFirstNode = rscanvas->GetIsParallelCanvas();
325 if (!isUiFirstNode && surfaceParams->GetOccludedByFilterCache()) {
326 SetDrawSkipType(DrawSkipType::FILTERCACHE_OCCLUSION_SKIP);
327 RS_TRACE_NAME_FMT("RSSurfaceRenderNodeDrawable::OnDraw filterCache occlusion skip [%s] %sAlpha: %f, "
328 "NodeId:%" PRIu64 "", name_.c_str(), surfaceParams->GetAbsDrawRect().ToString().c_str(),
329 surfaceParams->GetGlobalAlpha(), surfaceParams->GetId());
330 return;
331 }
332 hasSkipCacheLayer_ =
333 (surfaceParams->GetIsSecurityLayer() && !uniParam->GetSecExemption()) || surfaceParams->GetIsSkipLayer();
334 if (hasSkipCacheLayer_ && curDrawingCacheRoot_) {
335 curDrawingCacheRoot_->SetSkipCacheLayer(true);
336 }
337
338 Drawing::Region curSurfaceDrawRegion = CalculateVisibleRegion(*uniParam, *surfaceParams, *this, isUiFirstNode);
339 if (!isUiFirstNode) {
340 MergeDirtyRegionBelowCurSurface(*uniParam, curSurfaceDrawRegion);
341 }
342
343 if (!isUiFirstNode && uniParam->IsOpDropped() && surfaceParams->IsVisibleDirtyRegionEmpty(curSurfaceDrawRegion)) {
344 SetDrawSkipType(DrawSkipType::OCCLUSION_SKIP);
345 RS_TRACE_NAME_FMT("RSSurfaceRenderNodeDrawable::OnDraw occlusion skip SurfaceName:%s %sAlpha: %f, NodeId:"
346 "%" PRIu64 "", name_.c_str(), surfaceParams->GetAbsDrawRect().ToString().c_str(),
347 surfaceParams->GetGlobalAlpha(), surfaceParams->GetId());
348 return;
349 }
350 const auto &absDrawRect = surfaceParams->GetAbsDrawRect();
351 // warning : don't delete this trace or change trace level to optional !!!
352 RS_TRACE_NAME_FMT("RSSurfaceRenderNodeDrawable::OnDraw:[%s] (%d, %d, %d, %d)Alpha: %f", name_.c_str(),
353 absDrawRect.left_, absDrawRect.top_, absDrawRect.width_, absDrawRect.height_, surfaceParams->GetGlobalAlpha());
354
355 RS_LOGD("RSSurfaceRenderNodeDrawable::OnDraw node:%{public}" PRIu64 ", name:%{public}s,"
356 "OcclusionVisible:%{public}d Bound:%{public}s",
357 surfaceParams->GetId(), name_.c_str(), surfaceParams->GetOcclusionVisible(),
358 surfaceParams->GetBounds().ToString().c_str());
359
360 RSUiFirstProcessStateCheckerHelper stateCheckerHelper(
361 surfaceParams->GetFirstLevelNodeId(), surfaceParams->GetUifirstRootNodeId(), nodeId_);
362 if (!RSUiFirstProcessStateCheckerHelper::CheckMatchAndWaitNotify(*surfaceParams)) {
363 SetDrawSkipType(DrawSkipType::CHECK_MATCH_AND_WAIT_NOTIFY_FAIL);
364 return;
365 }
366
367 if (DealWithUIFirstCache(*rscanvas, *surfaceParams, *uniParam)) {
368 SetDrawSkipType(DrawSkipType::UI_FIRST_CACHE_SKIP);
369 return;
370 }
371
372 std::shared_ptr<Drawing::GPUContext> gpuContext = nullptr;
373 auto realTid = gettid();
374 if (realTid == RSUniRenderThread::Instance().GetTid()) {
375 gpuContext = RSUniRenderThread::Instance().GetRenderEngine()->GetRenderContext()->GetSharedDrGPUContext();
376 } else {
377 gpuContext = RSSubThreadManager::Instance()->GetGrContextFromSubThread(realTid);
378 }
379 RSTagTracker tagTracker(gpuContext.get(), surfaceParams->GetId(),
380 RSTagTracker::TAGTYPE::TAG_DRAW_SURFACENODE, surfaceParams->GetName());
381
382 // Draw base pipeline start
383 RSAutoCanvasRestore acr(rscanvas, RSPaintFilterCanvas::SaveType::kCanvasAndAlpha);
384 bool needOffscreen = (realTid == RSUniRenderThread::Instance().GetTid()) &&
385 surfaceParams->GetNeedOffscreen() && !rscanvas->GetTotalMatrix().IsIdentity() &&
386 surfaceParams->IsAppWindow() && GetName().substr(0, 3) != "SCB" && !IsHardwareEnabled() &&
387 (surfaceParams->GetVisibleRegion().Area() == surfaceParams->GetOpaqueRegion().Area());
388 curCanvas_ = rscanvas;
389 if (needOffscreen) {
390 releaseCount_ = 0;
391 if (!PrepareOffscreenRender()) {
392 needOffscreen = false;
393 }
394 } else {
395 if (offscreenSurface_ != nullptr) {
396 releaseCount_++;
397 if (releaseCount_ == MAX_RELEASE_FRAME) {
398 std::shared_ptr<Drawing::Surface> hold = offscreenSurface_;
399 RSUniRenderThread::Instance().PostTask([hold] {});
400 offscreenSurface_ = nullptr;
401 releaseCount_ = 0;
402 }
403 }
404 }
405
406 surfaceParams->ApplyAlphaAndMatrixToCanvas(*curCanvas_, !needOffscreen);
407
408 bool isSelfDrawingSurface = surfaceParams->GetSurfaceNodeType() == RSSurfaceNodeType::SELF_DRAWING_NODE &&
409 !surfaceParams->IsSpherizeValid();
410 if (isSelfDrawingSurface) {
411 SetSkip(surfaceParams->GetBuffer() != nullptr ? SkipType::SKIP_BACKGROUND_COLOR : SkipType::NONE);
412 // Restore in OnGeneralProcess
413 curCanvas_->Save();
414 }
415
416 if (surfaceParams->IsMainWindowType()) {
417 RSRenderNodeDrawable::ClearTotalProcessedNodeCount();
418 RSRenderNodeDrawable::ClearProcessedNodeCount();
419 if (!surfaceParams->GetNeedOffscreen()) {
420 curCanvas_->PushDirtyRegion(curSurfaceDrawRegion);
421 }
422 }
423
424 auto parentSurfaceMatrix = RSRenderParams::GetParentSurfaceMatrix();
425 RSRenderParams::SetParentSurfaceMatrix(curCanvas_->GetTotalMatrix());
426
427 // add a blending disable rect op behind floating window, to enable overdraw buffer feature on special gpu.
428 if (surfaceParams->IsLeashWindow() && RSSystemProperties::GetGpuOverDrawBufferOptimizeEnabled()
429 && surfaceParams->IsGpuOverDrawBufferOptimizeNode()) {
430 EnableGpuOverDrawDrawBufferOptimization(*curCanvas_, surfaceParams);
431 }
432
433 OnGeneralProcess(*curCanvas_, *surfaceParams, isSelfDrawingSurface);
434
435 if (needOffscreen) {
436 Drawing::AutoCanvasRestore acr(*canvasBackup_, true);
437 if (surfaceParams->HasSandBox()) {
438 canvasBackup_->SetMatrix(surfaceParams->GetParentSurfaceMatrix());
439 canvasBackup_->ConcatMatrix(surfaceParams->GetMatrix());
440 } else {
441 canvasBackup_->ConcatMatrix(surfaceParams->GetMatrix());
442 }
443 FinishOffscreenRender(
444 Drawing::SamplingOptions(Drawing::FilterMode::NEAREST, Drawing::MipmapMode::NONE));
445 RS_LOGD("FinishOffscreenRender %{public}s node type %{public}d", surfaceParams->GetName().c_str(),
446 int(surfaceParams->GetSurfaceNodeType()));
447 }
448
449 // Draw base pipeline end
450 if (surfaceParams->IsMainWindowType()) {
451 if (!surfaceParams->GetNeedOffscreen()) {
452 curCanvas_->PopDirtyRegion();
453 }
454 int processedNodes = RSRenderNodeDrawable::GetProcessedNodeCount();
455 AcquireFenceTracker::SetContainerNodeNum(processedNodes);
456 RS_TRACE_NAME_FMT("RSUniRenderThread::Render() the number of total ProcessedNodes: %d",
457 RSRenderNodeDrawable::GetTotalProcessedNodeCount());
458 const RSNodeStatsType nodeStats = CreateRSNodeStatsItem(
459 RSRenderNodeDrawable::GetTotalProcessedNodeCount(), GetId(), GetName());
460 RSNodeStats::GetInstance().AddNodeStats(nodeStats);
461 }
462
463 RSRenderParams::SetParentSurfaceMatrix(parentSurfaceMatrix);
464 }
465
MergeDirtyRegionBelowCurSurface(RSRenderThreadParams & uniParam,Drawing::Region & region)466 void RSSurfaceRenderNodeDrawable::MergeDirtyRegionBelowCurSurface(
467 RSRenderThreadParams& uniParam, Drawing::Region& region)
468 {
469 if (!renderParams_) {
470 return;
471 }
472 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(renderParams_.get());
473 if (!surfaceParams) {
474 return;
475 }
476 auto visibleRegion = surfaceParams->GetVisibleRegion();
477 if (surfaceParams->IsMainWindowType() && visibleRegion.IsEmpty()) {
478 return;
479 }
480 if (surfaceParams->IsMainWindowType() || surfaceParams->IsLeashWindow()) {
481 auto& accumulatedDirtyRegion = uniParam.GetAccumulatedDirtyRegion();
482 Occlusion::Region calcRegion;
483 if ((surfaceParams->IsMainWindowType() && surfaceParams->IsParentScaling()) ||
484 surfaceParams->IsSubSurfaceNode() || uniParam.IsAllSurfaceVisibleDebugEnabled()) {
485 calcRegion = visibleRegion;
486 } else if (!surfaceParams->GetTransparentRegion().IsEmpty()) {
487 auto transparentRegion = surfaceParams->GetTransparentRegion();
488 calcRegion = visibleRegion.And(transparentRegion);
489 }
490 if (!calcRegion.IsEmpty()) {
491 auto dirtyRegion = calcRegion.And(accumulatedDirtyRegion);
492 if (!dirtyRegion.IsEmpty()) {
493 for (auto& rect : dirtyRegion.GetRegionRects()) {
494 Drawing::Region tempRegion;
495 tempRegion.SetRect(Drawing::RectI(
496 rect.left_, rect.top_, rect.right_, rect.bottom_));
497 region.Op(tempRegion, Drawing::RegionOp::UNION);
498 }
499 }
500 }
501 // [planing] surfaceDirtyRegion can be optimized by visibleDirtyRegion in some case.
502 auto surfaceDirtyRegion = Occlusion::Region {
503 Occlusion::Rect{ GetSyncDirtyManager()->GetDirtyRegion() } };
504 accumulatedDirtyRegion.OrSelf(surfaceDirtyRegion);
505 // add children window dirty here for uifirst leasf window will not traverse cached children
506 if (surfaceParams->GetUifirstNodeEnableParam() != MultiThreadCacheType::NONE) {
507 auto childrenDirtyRegion = Occlusion::Region {
508 Occlusion::Rect{ surfaceParams->GetUifirstChildrenDirtyRectParam() } };
509 accumulatedDirtyRegion.OrSelf(childrenDirtyRegion);
510 }
511 }
512 }
513
OnCapture(Drawing::Canvas & canvas)514 void RSSurfaceRenderNodeDrawable::OnCapture(Drawing::Canvas& canvas)
515 {
516 if (!ShouldPaint()) {
517 return;
518 }
519
520 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(GetRenderParams().get());
521 if (!surfaceParams) {
522 RS_LOGE("RSSurfaceRenderNodeDrawable::OnCapture surfaceParams is nullptr");
523 return;
524 }
525
526 // HidePrivacyContent is only for UICapture or NoneSystemCalling-WindowCapture
527 bool isHiddenScene = canvas.GetUICapture() ||
528 (RSUniRenderThread::GetCaptureParam().isSingleSurface_ &&
529 !RSUniRenderThread::GetCaptureParam().isSystemCalling_);
530 if ((surfaceNodeType_ == RSSurfaceNodeType::UI_EXTENSION_COMMON_NODE ||
531 surfaceNodeType_ == RSSurfaceNodeType::UI_EXTENSION_SECURE_NODE) &&
532 isHiddenScene && surfaceParams->GetHidePrivacyContent()) {
533 RS_LOGE("RSSurfaceRenderNodeDrawable::OnCapture surfacenode nodeId:[%{public}" PRIu64
534 "] is not allowed to be captured", nodeId_);
535 return;
536 }
537
538 RSUiFirstProcessStateCheckerHelper stateCheckerHelper(
539 surfaceParams->GetFirstLevelNodeId(), surfaceParams->GetUifirstRootNodeId(), nodeId_);
540 auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
541 if (UNLIKELY(!uniParam)) {
542 RS_LOGE("RSSurfaceRenderNodeDrawable::OnCapture uniParam is nullptr");
543 return;
544 }
545
546 auto rscanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
547 if (!rscanvas) {
548 RS_LOGE("RSSurfaceRenderNodeDrawable::OnCapture, rscanvas us nullptr");
549 return;
550 }
551 rscanvas->SetHighContrast(RSUniRenderThread::Instance().IsHighContrastTextModeOn());
552 // process white list
553 auto whiteList = RSUniRenderThread::Instance().GetWhiteList();
554 SetVirtualScreenWhiteListRootId(whiteList, surfaceParams->GetId());
555
556 if (CheckIfSurfaceSkipInMirror(*surfaceParams)) {
557 return;
558 }
559
560 if (uniParam->IsOcclusionEnabled() && surfaceParams->IsMainWindowType() &&
561 surfaceParams->GetVisibleRegionInVirtual().IsEmpty() && whiteList.empty() &&
562 UNLIKELY(RSUniRenderThread::GetCaptureParam().isMirror_)) {
563 RS_TRACE_NAME("RSSurfaceRenderNodeDrawable::OnCapture occlusion skip :[" + name_ + "] " +
564 surfaceParams->GetAbsDrawRect().ToString());
565 return;
566 }
567
568 RS_TRACE_NAME("RSSurfaceRenderNodeDrawable::OnCapture:[" + name_ + "] " +
569 surfaceParams->GetAbsDrawRect().ToString() + "Alpha: " +
570 std::to_string(surfaceParams->GetGlobalAlpha()));
571 RSAutoCanvasRestore acr(rscanvas, RSPaintFilterCanvas::SaveType::kCanvasAndAlpha);
572
573 // First node don't need to concat matrix for application
574 if (RSUniRenderThread::GetCaptureParam().isFirstNode_) {
575 // Planning: If node is a sandbox.
576 rscanvas->MultiplyAlpha(surfaceParams->GetAlpha());
577 RSUniRenderThread::GetCaptureParam().isFirstNode_ = false;
578 } else {
579 surfaceParams->ApplyAlphaAndMatrixToCanvas(*rscanvas);
580 }
581
582 CaptureSurface(*rscanvas, *surfaceParams);
583 ResetVirtualScreenWhiteListRootId(surfaceParams->GetId());
584 }
585
CheckIfSurfaceSkipInMirror(const RSSurfaceRenderParams & surfaceParams)586 bool RSSurfaceRenderNodeDrawable::CheckIfSurfaceSkipInMirror(const RSSurfaceRenderParams& surfaceParams)
587 {
588 if (!RSUniRenderThread::GetCaptureParam().isMirror_) {
589 return false;
590 }
591 // Check black list.
592 const auto& blackList = RSUniRenderThread::Instance().GetBlackList();
593 if (surfaceParams.IsLeashWindow() && blackList.find(surfaceParams.GetLeashPersistentId()) != blackList.end()) {
594 RS_LOGD("RSSurfaceRenderNodeDrawable::CheckIfSurfaceSkipInMirror: \
595 (LeashPersistentId:[%{public}" PRIu64 "]) is in black list", surfaceParams.GetLeashPersistentId());
596 return true;
597 }
598 if (blackList.find(surfaceParams.GetId()) != blackList.end()) {
599 RS_LOGD("RSSurfaceRenderNodeDrawable::CheckIfSurfaceSkipInMirror: \
600 (surfaceParamsId:[%{public}" PRIu64 "]) is in black list", surfaceParams.GetId());
601 return true;
602 }
603 // Check white list.
604 const auto& whiteList = RSUniRenderThread::Instance().GetWhiteList();
605 if (!whiteList.empty() && RSUniRenderThread::GetCaptureParam().rootIdInWhiteList_ == INVALID_NODEID) {
606 RS_LOGD("RSSurfaceRenderNodeDrawable::CheckIfSurfaceSkipInMirror: \
607 (id:[%{public}" PRIu64 "]) isn't in white list", surfaceParams.GetId());
608 return true;
609 }
610 // To be deleted after captureWindow being deleted.
611 // Check weather can be skipped due to using screen recording optimization.
612 if (EnableRecordingOptimization(surfaceParams)) {
613 return true;
614 }
615 return false;
616 }
617
SetVirtualScreenWhiteListRootId(const std::unordered_set<NodeId> & whiteList,NodeId id)618 void RSSurfaceRenderNodeDrawable::SetVirtualScreenWhiteListRootId(
619 const std::unordered_set<NodeId>& whiteList, NodeId id)
620 {
621 if (whiteList.find(id) == whiteList.end()) {
622 return;
623 }
624 // don't update if it's ancestor has already set
625 if (RSUniRenderThread::GetCaptureParam().rootIdInWhiteList_ != INVALID_NODEID) {
626 return;
627 }
628 RSUniRenderThread::GetCaptureParam().rootIdInWhiteList_ = id;
629 }
630
ResetVirtualScreenWhiteListRootId(NodeId id)631 void RSSurfaceRenderNodeDrawable::ResetVirtualScreenWhiteListRootId(NodeId id)
632 {
633 // only reset by the node which sets the flag
634 if (RSUniRenderThread::GetCaptureParam().rootIdInWhiteList_ == id) {
635 RSUniRenderThread::GetCaptureParam().rootIdInWhiteList_ = INVALID_NODEID;
636 }
637 }
638
639 // To be deleted after captureWindow being deleted
EnableRecordingOptimization(const RSSurfaceRenderParams & surfaceParams)640 bool RSSurfaceRenderNodeDrawable::EnableRecordingOptimization(const RSSurfaceRenderParams& surfaceParams)
641 {
642 auto& threadParams = RSUniRenderThread::Instance().GetRSRenderThreadParams();
643 if (UNLIKELY(!threadParams)) {
644 return false;
645 }
646 NodeId nodeId = threadParams->GetRootIdOfCaptureWindow();
647 bool hasCaptureImg = threadParams->GetHasCaptureImg();
648 if (nodeId == surfaceParams.GetId()) {
649 RS_LOGD("RSSurfaceRenderNodeDrawable::EnableRecordingOptimization: (id:[%{public}" PRIu64 "])",
650 surfaceParams.GetId());
651 threadParams->SetStartVisit(true);
652 }
653 if (!hasCaptureImg || threadParams->GetStartVisit()) {
654 return false;
655 }
656 RS_LOGD("RSSurfaceRenderNodeDrawable::EnableRecordingOptimization: (id:[%{public}" PRIu64 "]) Skip layer.",
657 surfaceParams.GetId());
658 return true;
659 }
660
CaptureSurface(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams)661 void RSSurfaceRenderNodeDrawable::CaptureSurface(RSPaintFilterCanvas& canvas, RSSurfaceRenderParams& surfaceParams)
662 {
663 auto& uniParams = RSUniRenderThread::Instance().GetRSRenderThreadParams();
664 if (UNLIKELY(!uniParams)) {
665 RS_LOGE("RSSurfaceRenderNodeDrawable::CaptureSurface uniParams is nullptr");
666 return;
667 }
668 if ((surfaceParams.GetIsSecurityLayer() && !uniParams->GetSecExemption()) || surfaceParams.GetIsSkipLayer()) {
669 RS_LOGD("RSSurfaceRenderNodeDrawable::CaptureSurface: \
670 process RSSurfaceRenderNode(id:[%{public}" PRIu64 "] name:[%{public}s]) with security or skip layer.",
671 surfaceParams.GetId(), name_.c_str());
672 RS_TRACE_NAME("CaptureSurface with security or skip layer");
673 if (RSUniRenderThread::GetCaptureParam().isSingleSurface_) {
674 Drawing::Brush rectBrush;
675 rectBrush.SetColor(Drawing::Color::COLOR_WHITE);
676 canvas.AttachBrush(rectBrush);
677 canvas.DrawRect(Drawing::Rect(0, 0, surfaceParams.GetBounds().GetWidth(),
678 surfaceParams.GetBounds().GetHeight()));
679 canvas.DetachBrush();
680 }
681 return;
682 }
683
684 if (surfaceParams.GetIsProtectedLayer()) {
685 RS_LOGD("RSSurfaceRenderNodeDrawable::CaptureSurface: \
686 process RSSurfaceRenderNode(id:[%{public}" PRIu64 "] name:[%{public}s]) with protected layer.",
687 surfaceParams.GetId(), name_.c_str());
688 Drawing::Brush rectBrush;
689 rectBrush.SetColor(Drawing::Color::COLOR_BLACK);
690 canvas.AttachBrush(rectBrush);
691 canvas.DrawRect(Drawing::Rect(0, 0, surfaceParams.GetBounds().GetWidth(),
692 surfaceParams.GetBounds().GetHeight()));
693 canvas.DetachBrush();
694 return;
695 }
696
697 bool hwcEnable = surfaceParams.GetHardwareEnabled();
698 surfaceParams.SetHardwareEnabled(false);
699 RS_LOGD("HDR hasHdrPresent_:%{public}d", canvas.IsCapture());
700 bool hasHidePrivacyContent = surfaceParams.HasPrivacyContentLayer() &&
701 RSUniRenderThread::GetCaptureParam().isSingleSurface_ &&
702 !RSUniRenderThread::GetCaptureParam().isSystemCalling_;
703 if (!(surfaceParams.HasSecurityLayer() || surfaceParams.HasSkipLayer() || surfaceParams.HasProtectedLayer() ||
704 hasHdrPresent_ || hasHidePrivacyContent) && DealWithUIFirstCache(canvas, surfaceParams, *uniParams)) {
705 surfaceParams.SetHardwareEnabled(hwcEnable);
706 return;
707 }
708 surfaceParams.SetHardwareEnabled(hwcEnable);
709
710 // cannot useNodeMatchOptimize if leash window is on draw
711 auto cacheState = GetCacheSurfaceProcessedStatus();
712 auto useNodeMatchOptimize = cacheState != CacheProcessStatus::WAITING && cacheState != CacheProcessStatus::DOING;
713 if (!RSUiFirstProcessStateCheckerHelper::CheckMatchAndWaitNotify(surfaceParams, useNodeMatchOptimize)) {
714 RS_LOGE("RSSurfaceRenderNodeDrawable::OnCapture CheckMatchAndWaitNotify failed");
715 return;
716 }
717
718 bool isSelfDrawingSurface = surfaceParams.GetSurfaceNodeType() == RSSurfaceNodeType::SELF_DRAWING_NODE &&
719 !surfaceParams.IsSpherizeValid();
720 if (isSelfDrawingSurface) {
721 SetSkip(surfaceParams.GetBuffer() != nullptr ? SkipType::SKIP_BACKGROUND_COLOR : SkipType::NONE);
722 // Restore in OnGeneralProcess
723 canvas.Save();
724 }
725
726 auto parentSurfaceMatrix = RSRenderParams::GetParentSurfaceMatrix();
727 RSRenderParams::SetParentSurfaceMatrix(canvas.GetTotalMatrix());
728
729 OnGeneralProcess(canvas, surfaceParams, isSelfDrawingSurface);
730
731 RSRenderParams::SetParentSurfaceMatrix(parentSurfaceMatrix);
732 }
733
GetAncestorDisplayColorGamut(const RSSurfaceRenderParams & surfaceParams)734 GraphicColorGamut RSSurfaceRenderNodeDrawable::GetAncestorDisplayColorGamut(const RSSurfaceRenderParams& surfaceParams)
735 {
736 GraphicColorGamut targetColorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
737 auto ancestorDrawable = surfaceParams.GetAncestorDisplayDrawable().lock();
738 if (!ancestorDrawable) {
739 RS_LOGE("ancestorDrawable return nullptr");
740 return targetColorGamut;
741 }
742 auto ancestorDisplayDrawable = std::static_pointer_cast<RSDisplayRenderNodeDrawable>(ancestorDrawable);
743 if (!ancestorDisplayDrawable) {
744 RS_LOGE("ancestorDisplayDrawable return nullptr");
745 return targetColorGamut;
746 }
747 auto& ancestorParam = ancestorDrawable->GetRenderParams();
748 if (!ancestorParam) {
749 RS_LOGE("ancestorParam return nullptr");
750 return targetColorGamut;
751 }
752
753 auto renderParams = static_cast<RSDisplayRenderParams*>(ancestorParam.get());
754 targetColorGamut = renderParams->GetNewColorSpace();
755 RS_LOGD("params.targetColorGamut is %{public}d in DealWithSelfDrawingNodeBuffer", targetColorGamut);
756 return targetColorGamut;
757 }
758
DealWithSelfDrawingNodeBuffer(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams)759 void RSSurfaceRenderNodeDrawable::DealWithSelfDrawingNodeBuffer(
760 RSPaintFilterCanvas& canvas, RSSurfaceRenderParams& surfaceParams)
761 {
762 if (surfaceParams.GetHardwareEnabled() && !RSUniRenderThread::IsInCaptureProcess()) {
763 if (!IsHardwareEnabledTopSurface() && !surfaceParams.IsLayerTop()) {
764 ClipHoleForSelfDrawingNode(canvas, surfaceParams);
765 }
766 return;
767 }
768 if (surfaceParams.IsInFixedRotation()) {
769 DrawBufferForRotationFixed(canvas, surfaceParams);
770 return;
771 }
772
773 RSAutoCanvasRestore arc(&canvas);
774 surfaceParams.SetGlobalAlpha(1.0f);
775 pid_t threadId = gettid();
776 auto params = RSUniRenderUtil::CreateBufferDrawParam(*this, false, threadId);
777 params.targetColorGamut = GetAncestorDisplayColorGamut(surfaceParams);
778 #ifdef USE_VIDEO_PROCESSING_ENGINE
779 params.sdrNits = surfaceParams.GetSdrNit();
780 params.tmoNits = surfaceParams.GetDisplayNit();
781 params.displayNits = params.tmoNits / std::pow(surfaceParams.GetBrightnessRatio(), GAMMA2_2); // gamma 2.2
782 #endif
783 #ifdef OHOS_BUILD_ENABLE_MAGICCURSOR
784 if (IsHardwareEnabledTopSurface() && RSUniRenderThread::Instance().GetRSRenderThreadParams()->HasMirrorDisplay()) {
785 RSPointerRenderManager::GetInstance().SetCacheImgForPointer(canvas.GetSurface()->GetImageSnapshot());
786 }
787 #endif
788
789 DrawSelfDrawingNodeBuffer(canvas, surfaceParams, params);
790 }
791
ClipHoleForSelfDrawingNode(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams)792 void RSSurfaceRenderNodeDrawable::ClipHoleForSelfDrawingNode(RSPaintFilterCanvas& canvas,
793 RSSurfaceRenderParams& surfaceParams)
794 {
795 RSAutoCanvasRestore arc(&canvas);
796 auto bounds = surfaceParams.GetBounds();
797 canvas.ClipRect({std::round(bounds.GetLeft()), std::round(bounds.GetTop()),
798 std::round(bounds.GetRight()), std::round(bounds.GetBottom())});
799 canvas.Clear(Drawing::Color::COLOR_TRANSPARENT);
800 }
801
DrawBufferForRotationFixed(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams)802 void RSSurfaceRenderNodeDrawable::DrawBufferForRotationFixed(RSPaintFilterCanvas& canvas,
803 RSSurfaceRenderParams& surfaceParams)
804 {
805 ClipHoleForSelfDrawingNode(canvas, surfaceParams);
806
807 Drawing::Brush brush;
808 brush.SetBlendMode(Drawing::BlendMode::DST_OVER);
809 Drawing::SaveLayerOps layerOps(nullptr, &brush);
810 canvas.SaveLayer(layerOps);
811
812 Drawing::Matrix inverse;
813 if (!(surfaceParams.GetLayerInfo().matrix.Invert(inverse))) {
814 RS_LOGE("DrawBufferForRotationFixed failed to get invert matrix");
815 }
816 canvas.ConcatMatrix(inverse);
817 auto params = RSUniRenderUtil::CreateBufferDrawParamForRotationFixed(*this, surfaceParams);
818 RSUniRenderThread::Instance().GetRenderEngine()->DrawSurfaceNodeWithParams(canvas, *this, params);
819 canvas.Restore();
820 }
821
DrawSelfDrawingNodeBuffer(RSPaintFilterCanvas & canvas,const RSSurfaceRenderParams & surfaceParams,BufferDrawParam & params)822 void RSSurfaceRenderNodeDrawable::DrawSelfDrawingNodeBuffer(
823 RSPaintFilterCanvas& canvas, const RSSurfaceRenderParams& surfaceParams, BufferDrawParam& params)
824 {
825 auto bgColor = surfaceParams.GetBackgroundColor();
826 auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
827 if ((surfaceParams.GetSelfDrawingNodeType() != SelfDrawingNodeType::VIDEO) &&
828 (bgColor != RgbPalette::Transparent())) {
829 Drawing::Brush brush;
830 brush.SetColor(Drawing::Color(bgColor.AsArgbInt()));
831 if (HasCornerRadius(surfaceParams)) {
832 auto bounds = RSPropertiesPainter::Rect2DrawingRect({ 0, 0,
833 std::round(surfaceParams.GetBounds().GetWidth()), std::round(surfaceParams.GetBounds().GetHeight()) });
834 Drawing::SaveLayerOps layerOps(&bounds, nullptr);
835 canvas.SaveLayer(layerOps);
836 canvas.AttachBrush(brush);
837 canvas.DrawRoundRect(RSPropertiesPainter::RRect2DrawingRRect(surfaceParams.GetRRect()));
838 canvas.DetachBrush();
839 renderEngine->DrawSurfaceNodeWithParams(canvas, *this, params);
840 canvas.Restore();
841 } else {
842 canvas.AttachBrush(brush);
843 canvas.DrawRect(surfaceParams.GetBounds());
844 canvas.DetachBrush();
845 renderEngine->DrawSurfaceNodeWithParams(canvas, *this, params);
846 }
847 } else {
848 renderEngine->DrawSurfaceNodeWithParams(canvas, *this, params);
849 }
850 }
851
HasCornerRadius(const RSSurfaceRenderParams & surfaceParams) const852 bool RSSurfaceRenderNodeDrawable::HasCornerRadius(const RSSurfaceRenderParams& surfaceParams) const
853 {
854 auto rrect = surfaceParams.GetRRect();
855 for (auto index = 0; index < CORNER_SIZE; ++index) {
856 if (!ROSEN_EQ(rrect.radius_[index].x_, 0.f) || !ROSEN_EQ(rrect.radius_[index].y_, 0.f)) {
857 return true;
858 }
859 }
860 return false;
861 }
862
DealWithUIFirstCache(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams,RSRenderThreadParams & uniParams)863 bool RSSurfaceRenderNodeDrawable::DealWithUIFirstCache(
864 RSPaintFilterCanvas& canvas, RSSurfaceRenderParams& surfaceParams, RSRenderThreadParams& uniParams)
865 {
866 auto enableType = surfaceParams.GetUifirstNodeEnableParam();
867 auto cacheState = GetCacheSurfaceProcessedStatus();
868 if ((!RSUniRenderThread::GetCaptureParam().isSnapshot_ && enableType == MultiThreadCacheType::NONE &&
869 // WAITING may change to DOING in subThread at any time
870 cacheState != CacheProcessStatus::WAITING && cacheState != CacheProcessStatus::DOING) ||
871 (RSUniRenderThread::GetCaptureParam().isSnapshot_ && !HasCachedTexture())) {
872 return false;
873 }
874 RS_TRACE_NAME_FMT("DrawUIFirstCache [%s] %lld, type %d",
875 name_.c_str(), surfaceParams.GetId(), enableType);
876 RSUifirstManager::Instance().AddReuseNode(surfaceParams.GetId());
877 Drawing::Rect bounds = GetRenderParams() ? GetRenderParams()->GetBounds() : Drawing::Rect(0, 0, 0, 0);
878 RSAutoCanvasRestore acr(&canvas);
879 // Alpha and matrix have been applied in func CaptureSurface
880 if (!RSUniRenderThread::GetCaptureParam().isSnapshot_ && !RSUniRenderThread::GetCaptureParam().isMirror_) {
881 canvas.MultiplyAlpha(surfaceParams.GetAlpha());
882 canvas.ConcatMatrix(surfaceParams.GetMatrix());
883 }
884 bool useDmaBuffer = UseDmaBuffer();
885 DrawBackground(canvas, bounds);
886 bool drawCacheSuccess = true;
887 if (surfaceParams.GetUifirstUseStarting() != INVALID_NODEID) {
888 drawCacheSuccess = DrawUIFirstCacheWithStarting(canvas, surfaceParams.GetUifirstUseStarting());
889 } else {
890 bool canSkipFirstWait = (enableType == MultiThreadCacheType::ARKTS_CARD) &&
891 uniParams.GetUIFirstCurrentFrameCanSkipFirstWait();
892 drawCacheSuccess = useDmaBuffer ?
893 DrawUIFirstCacheWithDma(canvas, surfaceParams) : DrawUIFirstCache(canvas, canSkipFirstWait);
894 }
895 if (!drawCacheSuccess) {
896 RS_TRACE_NAME_FMT("[%s] reuse failed!", name_.c_str());
897 }
898 DrawForeground(canvas, bounds);
899 if (uniParams.GetUIFirstDebugEnabled()) {
900 DrawUIFirstDfx(canvas, enableType, surfaceParams, drawCacheSuccess);
901 }
902 return true;
903 }
904
DrawUIFirstDfx(RSPaintFilterCanvas & canvas,MultiThreadCacheType enableType,RSSurfaceRenderParams & surfaceParams,bool drawCacheSuccess)905 void RSSurfaceRenderNodeDrawable::DrawUIFirstDfx(RSPaintFilterCanvas& canvas, MultiThreadCacheType enableType,
906 RSSurfaceRenderParams& surfaceParams, bool drawCacheSuccess)
907 {
908 auto sizeDebug = surfaceParams.GetCacheSize();
909 Drawing::Brush rectBrush;
910 if (drawCacheSuccess) {
911 if (enableType == MultiThreadCacheType::ARKTS_CARD) {
912 // rgba: Alpha 128, blue 128
913 rectBrush.SetColor(Drawing::Color(0, 0, 128, 128));
914 } else {
915 // rgba: Alpha 128, green 128, blue 128
916 rectBrush.SetColor(Drawing::Color(0, 128, 128, 128));
917 }
918 } else {
919 // rgba: Alpha 128, red 128
920 rectBrush.SetColor(Drawing::Color(128, 0, 0, 128));
921 }
922 canvas.AttachBrush(rectBrush);
923 canvas.DrawRect(Drawing::Rect(0, 0, sizeDebug.x_, sizeDebug.y_));
924 canvas.DetachBrush();
925 }
926
EnableGpuOverDrawDrawBufferOptimization(Drawing::Canvas & canvas,RSSurfaceRenderParams * surfaceParams)927 void RSSurfaceRenderNodeDrawable::EnableGpuOverDrawDrawBufferOptimization(Drawing::Canvas& canvas,
928 RSSurfaceRenderParams* surfaceParams)
929 {
930 const Vector4f& radius = surfaceParams->GetOverDrawBufferNodeCornerRadius();
931 if (radius.IsZero()) {
932 return;
933 }
934 RS_OPTIONAL_TRACE_NAME_FMT("EnableGpuOverDrawDrawBufferOptimization Id:%" PRIu64 "", surfaceParams->GetId());
935 const Drawing::Rect& bounds = surfaceParams->GetFrameRect();
936 Drawing::Brush brush;
937 // must set src blend mode, so overdraw buffer feature can enabled.
938 brush.SetBlendMode(Drawing::BlendMode::SRC);
939 // cause the rect will be covered by the child background node, so we just add a white rect
940 brush.SetColor(Drawing::Color::COLOR_WHITE);
941 canvas.AttachBrush(brush);
942 Drawing::AutoCanvasRestore arc(canvas, true);
943 canvas.Translate(radius.x_, radius.y_);
944 canvas.DrawRect(Drawing::Rect {0, 0, bounds.GetWidth() - 2 * radius.x_, bounds.GetHeight() - 2 * radius.y_});
945 canvas.DetachBrush();
946 }
947
GetVisibleDirtyRegion() const948 const Occlusion::Region& RSSurfaceRenderNodeDrawable::GetVisibleDirtyRegion() const
949 {
950 return visibleDirtyRegion_;
951 }
952
SetVisibleDirtyRegion(const Occlusion::Region & region)953 void RSSurfaceRenderNodeDrawable::SetVisibleDirtyRegion(const Occlusion::Region& region)
954 {
955 visibleDirtyRegion_ = region;
956 }
957
SetAlignedVisibleDirtyRegion(const Occlusion::Region & alignedRegion)958 void RSSurfaceRenderNodeDrawable::SetAlignedVisibleDirtyRegion(const Occlusion::Region& alignedRegion)
959 {
960 alignedVisibleDirtyRegion_ = alignedRegion;
961 }
962
SetGlobalDirtyRegion(Occlusion::Region region)963 void RSSurfaceRenderNodeDrawable::SetGlobalDirtyRegion(Occlusion::Region region)
964 {
965 if (!GetRenderParams()) {
966 return;
967 }
968 auto visibleRegion = GetRenderParams()->GetVisibleRegion();
969 globalDirtyRegion_ = visibleRegion.And(region);
970 globalDirtyRegionIsEmpty_ = globalDirtyRegion_.IsEmpty();
971 }
972
GetGlobalDirtyRegion() const973 const Occlusion::Region& RSSurfaceRenderNodeDrawable::GetGlobalDirtyRegion() const
974 {
975 return globalDirtyRegion_;
976 }
977
SetDirtyRegionAlignedEnable(bool enable)978 void RSSurfaceRenderNodeDrawable::SetDirtyRegionAlignedEnable(bool enable)
979 {
980 isDirtyRegionAlignedEnable_ = enable;
981 }
982
SetDirtyRegionBelowCurrentLayer(Occlusion::Region & region)983 void RSSurfaceRenderNodeDrawable::SetDirtyRegionBelowCurrentLayer(Occlusion::Region& region)
984 {
985 #ifndef ROSEN_CROSS_PLATFORM
986 if (!renderParams_) {
987 return;
988 }
989 Occlusion::Rect dirtyRect { renderParams_->GetOldDirtyInSurface() };
990 Occlusion::Region dirtyRegion { dirtyRect };
991 dirtyRegionBelowCurrentLayer_ = dirtyRegion.And(region);
992 dirtyRegionBelowCurrentLayerIsEmpty_ = dirtyRegionBelowCurrentLayer_.IsEmpty();
993 #endif
994 }
995
GetSyncDirtyManager() const996 std::shared_ptr<RSDirtyRegionManager> RSSurfaceRenderNodeDrawable::GetSyncDirtyManager() const
997 {
998 return syncDirtyManager_;
999 }
1000
1001 #ifndef ROSEN_CROSS_PLATFORM
RegisterDeleteBufferListenerOnSync(sptr<IConsumerSurface> consumer)1002 void RSSurfaceRenderNodeDrawable::RegisterDeleteBufferListenerOnSync(sptr<IConsumerSurface> consumer)
1003 {
1004 auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
1005 if (!renderEngine || !consumerOnDraw_) {
1006 return;
1007 }
1008 renderEngine->RegisterDeleteBufferListener(consumerOnDraw_);
1009 }
1010 #endif
1011
1012 } // namespace OHOS::Rosen::DrawableV2
1013