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