• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_effect_render_node_drawable.h"
17 
18 #include "pipeline/rs_uni_render_thread.h"
19 #include "platform/common/rs_log.h"
20 
21 namespace OHOS::Rosen::DrawableV2 {
22 RSEffectRenderNodeDrawable::Registrar RSEffectRenderNodeDrawable::instance_;
23 
RSEffectRenderNodeDrawable(std::shared_ptr<const RSRenderNode> && node)24 RSEffectRenderNodeDrawable::RSEffectRenderNodeDrawable(std::shared_ptr<const RSRenderNode>&& node)
25     : RSRenderNodeDrawable(std::move(node))
26 {}
27 
OnGenerate(std::shared_ptr<const RSRenderNode> node)28 RSRenderNodeDrawable::Ptr RSEffectRenderNodeDrawable::OnGenerate(std::shared_ptr<const RSRenderNode> node)
29 {
30     return new RSEffectRenderNodeDrawable(std::move(node));
31 }
32 
OnDraw(Drawing::Canvas & canvas)33 void RSEffectRenderNodeDrawable::OnDraw(Drawing::Canvas& canvas)
34 {
35     SetDrawSkipType(DrawSkipType::NONE);
36     if (!ShouldPaint()) {
37         SetDrawSkipType(DrawSkipType::SHOULD_NOT_PAINT);
38         return;
39     }
40 
41     RS_LOGD("RSEffectRenderNodeDrawable::OnDraw node: %{public}" PRIu64, nodeId_);
42     auto effectParams = static_cast<RSEffectRenderParams*>(GetRenderParams().get());
43     if (!effectParams) {
44         SetDrawSkipType(DrawSkipType::RENDER_PARAMS_NULL);
45         RS_LOGE("RSSurfaceRenderNodeDrawable::OnDraw params is nullptr");
46         return;
47     }
48     auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
49     RSAutoCanvasRestore acr(paintFilterCanvas, RSPaintFilterCanvas::SaveType::kAll);
50 
51     effectParams->ApplyAlphaAndMatrixToCanvas(*paintFilterCanvas);
52     auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
53     if ((UNLIKELY(!uniParam) || uniParam->IsOpDropped()) && GetOpDropped() &&
54         QuickReject(canvas, effectParams->GetLocalDrawRect())) {
55         SetDrawSkipType(DrawSkipType::OCCLUSION_SKIP);
56         return;
57     }
58     const Drawing::Rect& bounds = GetRenderParams() ? GetRenderParams()->GetFrameRect() : Drawing::Rect(0, 0, 0, 0);
59 
60     if (!GenerateEffectDataOnDemand(effectParams, canvas, bounds, paintFilterCanvas)) {
61         SetDrawSkipType(DrawSkipType::GENERATE_EFFECT_DATA_ON_DEMAND_FAIL);
62         return;
63     }
64 
65     RSRenderNodeDrawableAdapter::DrawImpl(canvas, bounds, drawCmdIndex_.childrenIndex_);
66 }
67 
GenerateEffectDataOnDemand(RSEffectRenderParams * effectParams,Drawing::Canvas & canvas,const Drawing::Rect & bounds,RSPaintFilterCanvas * paintFilterCanvas)68 bool RSEffectRenderNodeDrawable::GenerateEffectDataOnDemand(RSEffectRenderParams* effectParams,
69     Drawing::Canvas& canvas, const Drawing::Rect& bounds, RSPaintFilterCanvas* paintFilterCanvas)
70 {
71     if (drawCmdIndex_.childrenIndex_ == -1) {
72         // case 0: No children, skip
73         return false;
74     } else if (drawCmdIndex_.backgroundFilterIndex_ == -1 || !RSSystemProperties::GetEffectMergeEnabled() ||
75         !effectParams->GetHasEffectChildren()) {
76         // case 1: no blur or no need to blur, do nothing
77     } else if (drawCmdIndex_.backgroundImageIndex_ == -1 || effectParams->GetCacheValid()) {
78         // case 2: dynamic blur, blur the underlay content
79         // case 3a: static blur with valid cache, reuse cache
80         Drawing::AutoCanvasRestore acr(canvas, true);
81         canvas.ClipIRect(Drawing::RectI(0, 0, bounds.GetWidth(), bounds.GetHeight()));
82         RSRenderNodeDrawableAdapter::DrawImpl(canvas, bounds, drawCmdIndex_.backgroundFilterIndex_);
83     } else {
84         // case 3b: static blur without valid cache, draw background image and blur
85         Drawing::AutoCanvasRestore acr(canvas, true);
86         canvas.ClipIRect(Drawing::RectI(0, 0, bounds.GetWidth(), bounds.GetHeight()));
87         auto surface = canvas.GetSurface();
88         if (!surface) {
89             ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundImageAsEffect surface is null");
90             return false;
91         }
92         // extract clip bounds
93         auto currentRect = canvas.GetDeviceClipBounds();
94         // create offscreen surface
95         auto offscreenSurface = surface->MakeSurface(currentRect.GetWidth(), currentRect.GetHeight());
96         if (!offscreenSurface) {
97             ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundImageAsEffect offscreenSurface is null");
98             return false;
99         }
100         auto offscreenCanvas = std::make_unique<RSPaintFilterCanvas>(offscreenSurface.get());
101         // copy current matrix to offscreen canvas, while aligned with current rect
102         auto currentMatrix = canvas.GetTotalMatrix();
103         currentMatrix.PostTranslate(-currentRect.GetLeft(), -currentRect.GetTop());
104         offscreenCanvas->SetMatrix(currentMatrix);
105         // draw background image and blur
106         RSRenderNodeDrawableAdapter::DrawImpl(*offscreenCanvas, bounds, drawCmdIndex_.backgroundImageIndex_);
107         RSRenderNodeDrawableAdapter::DrawImpl(*offscreenCanvas, bounds, drawCmdIndex_.backgroundFilterIndex_);
108         // copy effect data from offscreen canvas to current canvas, aligned with current rect
109         auto effectData = offscreenCanvas->GetEffectData();
110         effectData->cachedRect_.Offset(currentRect.GetLeft(), currentRect.GetTop());
111         paintFilterCanvas->SetEffectData(effectData);
112     }
113     return true;
114 }
115 
OnCapture(Drawing::Canvas & canvas)116 void RSEffectRenderNodeDrawable::OnCapture(Drawing::Canvas& canvas)
117 {
118     RSEffectRenderNodeDrawable::OnDraw(canvas);
119 }
120 } // namespace OHOS::Rosen::DrawableV2
121