1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "pipeline/rs_render_engine.h"
17 #include "pipeline/rs_divided_render_util.h"
18 #include "pipeline/rs_main_thread.h"
19 #include "string_utils.h"
20 #include "render/rs_drawing_filter.h"
21 #include "render/rs_skia_filter.h"
22 #include "rs_trace.h"
23 #include "platform/common/rs_log.h"
24 
25 #include "image/image.h"
26 
27 namespace OHOS {
28 namespace Rosen {
29 namespace {
30 constexpr float GAMMA2_2 = 2.2f;
31 }
DrawSurfaceNodeWithParams(RSPaintFilterCanvas & canvas,RSSurfaceRenderNode & node,BufferDrawParam & params,PreProcessFunc preProcess,PostProcessFunc postProcess)32 void RSRenderEngine::DrawSurfaceNodeWithParams(RSPaintFilterCanvas& canvas, RSSurfaceRenderNode& node,
33     BufferDrawParam& params, PreProcessFunc preProcess, PostProcessFunc postProcess)
34 {
35     if (!params.useCPU) {
36         RegisterDeleteBufferListener(node.GetRSSurfaceHandler()->GetConsumer());
37     }
38 
39     auto nodePreProcessFunc = [&preProcess, &node](RSPaintFilterCanvas& canvas, BufferDrawParam& params) {
40         // call the preprocess func passed in first.
41         if (preProcess != nullptr) {
42             preProcess(canvas, params);
43         }
44 
45         // call RSSurfaceNode's common preprocess func.
46         RSRenderEngine::RSSurfaceNodeCommonPreProcess(node, canvas, params);
47     };
48 
49     auto nodePostProcessFunc = [&postProcess, &node](RSPaintFilterCanvas& canvas, BufferDrawParam& params) {
50         // call the postProcess func passed in first.
51         if (postProcess != nullptr) {
52             postProcess(canvas, params);
53         }
54 
55         // call RSSurfaceNode's common postProcess func.
56         RSRenderEngine::RSSurfaceNodeCommonPostProcess(node, canvas, params);
57     };
58 
59     // draw shadow(should before canvas.clipRect in DrawWithParams()).
60     const auto& property = node.GetRenderProperties();
61     RSPropertiesPainter::DrawShadow(property, canvas, &params.clipRRect);
62     RSPropertiesPainter::DrawOutline(property, canvas);
63 
64     DrawWithParams(canvas, params, nodePreProcessFunc, nodePostProcessFunc);
65 }
66 
67 #ifdef USE_VIDEO_PROCESSING_ENGINE
DrawLayers(RSPaintFilterCanvas & canvas,const std::vector<LayerInfoPtr> & layers,bool forceCPU,const ScreenInfo & screenInfo,GraphicColorGamut colorGamut)68 void RSRenderEngine::DrawLayers(RSPaintFilterCanvas& canvas, const std::vector<LayerInfoPtr>& layers, bool forceCPU,
69     const ScreenInfo& screenInfo, GraphicColorGamut colorGamut)
70 #else
71 void RSRenderEngine::DrawLayers(RSPaintFilterCanvas& canvas, const std::vector<LayerInfoPtr>& layers, bool forceCPU,
72     const ScreenInfo& screenInfo)
73 #endif
74 {
75     (void) screenInfo;
76 #ifdef USE_VIDEO_PROCESSING_ENGINE
77     (void) colorGamut;
78 #endif
79     const auto& nodeMap = RSMainThread::Instance()->GetContext().GetNodeMap();
80     for (const auto& layer : layers) {
81         if (layer == nullptr) {
82             continue;
83         }
84         if (layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE ||
85             layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE_CLEAR) {
86             continue;
87         }
88         auto nodePtr = nodeMap.GetRenderNode<RSRenderNode>(layer->GetNodeId());
89         if (nodePtr == nullptr) {
90             RS_LOGE("RSRenderEngine::DrawLayers: node is nullptr!");
91             continue;
92         }
93 
94         auto saveCount = canvas.GetSaveCount();
95         if (nodePtr->IsInstanceOf<RSSurfaceRenderNode>()) {
96             RSSurfaceRenderNode& node = *(static_cast<RSSurfaceRenderNode*>(nodePtr.get()));
97             if (layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT_CLEAR ||
98                 layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_TUNNEL) {
99                 ClipHoleForLayer(canvas, node);
100                 canvas.RestoreToCount(saveCount);
101                 continue;
102             }
103             RS_LOGD("RSRenderEngine::DrawLayers dstRect[%{public}d %{public}d %{public}d %{public}d]",
104                 layer->GetLayerSize().x, layer->GetLayerSize().y, layer->GetLayerSize().w, layer->GetLayerSize().h);
105             const std::vector<GraphicIRect>& dirtyRegions = layer->GetDirtyRegions();
106             for (auto iter = dirtyRegions.begin(); iter != dirtyRegions.end(); iter++) {
107                 RS_LOGD("RSRenderEngine::DrawLayers SrcRect[%{public}d %{public}d %{public}d %{public}d]",
108                     iter->x, iter->y, iter->w, iter->h);
109             }
110             auto params = RSDividedRenderUtil::CreateBufferDrawParam(node, false, false, forceCPU);
111 #ifdef USE_VIDEO_PROCESSING_ENGINE
112             params.tmoNits = layer->GetDisplayNit();
113             params.displayNits = params.tmoNits / std::pow(layer->GetBrightnessRatio(), GAMMA2_2); // gamma 2.2
114             if (node.GetRSSurfaceHandler() != nullptr &&
115                 !CheckIsHdrSurfaceBuffer(node.GetRSSurfaceHandler()->GetBuffer())) {
116                 params.brightnessRatio = layer->GetBrightnessRatio();
117             } else {
118                 params.isHdrRedraw = true;
119             }
120 #endif
121             DrawSurfaceNode(canvas, node, params);
122         } else {
123             // Probably never reach this branch.
124             RS_LOGE("RSRenderEngine::DrawLayers: unexpected node type!");
125             continue;
126         }
127         canvas.RestoreToCount(saveCount);
128     }
129 }
130 
DrawWithParams(RSPaintFilterCanvas & canvas,BufferDrawParam & params,PreProcessFunc preProcess,PostProcessFunc postProcess)131 void RSRenderEngine::DrawWithParams(RSPaintFilterCanvas& canvas, BufferDrawParam& params,
132     PreProcessFunc preProcess, PostProcessFunc postProcess)
133 {
134     if (params.setColorFilter) {
135         SetColorFilterModeToPaint(params.paint);
136     }
137 
138     canvas.Save();
139 
140     RSBaseRenderUtil::SetPropertiesForCanvas(canvas, params);
141 
142     if (preProcess != nullptr) {
143         preProcess(canvas, params);
144     }
145 
146     if (params.useCPU) {
147         RSBaseRenderEngine::DrawBuffer(canvas, params);
148     } else {
149         RSBaseRenderEngine::DrawImage(canvas, params);
150     }
151 
152     if (postProcess != nullptr) {
153         postProcess(canvas, params);
154     }
155 
156     canvas.Restore();
157 }
158 
RSSurfaceNodeCommonPreProcess(RSSurfaceRenderNode & node,RSPaintFilterCanvas & canvas,BufferDrawParam & params)159 void RSRenderEngine::RSSurfaceNodeCommonPreProcess(RSSurfaceRenderNode& node, RSPaintFilterCanvas& canvas,
160     BufferDrawParam& params)
161 {
162     const auto& property = node.GetRenderProperties();
163 
164     // draw mask.
165     RectF maskBounds(0, 0, params.dstRect.GetWidth(), params.dstRect.GetHeight());
166     RSPropertiesPainter::DrawMask(
167         node.GetRenderProperties(), canvas, RSPropertiesPainter::Rect2DrawingRect(maskBounds));
168 
169     // draw background filter (should execute this filter before drawing buffer/image).
170     RSPropertiesPainter::DrawFilter(property, canvas, FilterType::BACKGROUND_FILTER,
171         Drawing::Rect(0, 0, params.srcRect.GetWidth(), params.srcRect.GetHeight()));
172 }
173 
RSSurfaceNodeCommonPostProcess(RSSurfaceRenderNode & node,RSPaintFilterCanvas & canvas,BufferDrawParam & params)174 void RSRenderEngine::RSSurfaceNodeCommonPostProcess(RSSurfaceRenderNode& node, RSPaintFilterCanvas& canvas,
175     BufferDrawParam& params)
176 {
177     const auto& property = node.GetRenderProperties();
178 
179     // draw preprocess filter (should execute this filter after drawing buffer/image).
180     RSPropertiesPainter::DrawFilter(property, canvas, FilterType::FOREGROUND_FILTER,
181         Drawing::Rect(0, 0, params.srcRect.GetWidth(), params.srcRect.GetHeight()));
182 }
183 
DrawSurfaceNode(RSPaintFilterCanvas & canvas,RSSurfaceRenderNode & node,BufferDrawParam & params)184 void RSRenderEngine::DrawSurfaceNode(RSPaintFilterCanvas& canvas, RSSurfaceRenderNode& node,
185     BufferDrawParam& params)
186 {
187     const float adaptiveDstWidth = params.dstRect.GetWidth() * mirrorAdaptiveCoefficient_;
188     const float adaptiveDstHeight = params.dstRect.GetHeight() * mirrorAdaptiveCoefficient_;
189     params.dstRect = Drawing::Rect(0, 0, adaptiveDstWidth, adaptiveDstHeight);
190     const float translateX = params.matrix.Get(Drawing::Matrix::Index::TRANS_X) * mirrorAdaptiveCoefficient_;
191     const float translateY = params.matrix.Get(Drawing::Matrix::Index::TRANS_Y) * mirrorAdaptiveCoefficient_;
192     params.matrix.Set(Drawing::Matrix::Index::TRANS_X, translateX);
193     params.matrix.Set(Drawing::Matrix::Index::TRANS_Y, translateY);
194     const auto& clipRect = params.clipRect;
195     auto clipLeft = clipRect.GetLeft() * mirrorAdaptiveCoefficient_;
196     auto clipTop = clipRect.GetTop() * mirrorAdaptiveCoefficient_;
197     params.clipRect = Drawing::Rect(
198         clipLeft, clipTop, clipLeft + clipRect.GetWidth() * mirrorAdaptiveCoefficient_,
199         clipTop + clipRect.GetHeight() * mirrorAdaptiveCoefficient_);
200 
201     DrawSurfaceNodeWithParams(canvas, node, params, nullptr, nullptr);
202 }
203 
ClipHoleForLayer(RSPaintFilterCanvas & canvas,RSSurfaceRenderNode & node)204 void RSRenderEngine::ClipHoleForLayer(RSPaintFilterCanvas& canvas, RSSurfaceRenderNode& node)
205 {
206     BufferDrawParam params = RSDividedRenderUtil::CreateBufferDrawParam(node, false, true);
207 
208     std::string traceInfo;
209     AppendFormat(traceInfo, "Node name:%s ClipHole[%d %d %d %d]", node.GetName().c_str(),
210         params.clipRect.GetLeft(), params.clipRect.GetTop(), params.clipRect.GetWidth(), params.clipRect.GetHeight());
211     RS_LOGD("RSRenderEngine::Redraw layer composition ClipHoleForLayer, %{public}s.", traceInfo.c_str());
212     RS_TRACE_NAME(traceInfo);
213 
214     canvas.Save();
215     canvas.ClipRect(params.clipRect, Drawing::ClipOp::INTERSECT, false);
216     canvas.Clear(Drawing::Color::COLOR_TRANSPARENT);
217     canvas.Restore();
218     return;
219 }
220 
SetColorFilterModeToPaint(Drawing::Brush & paint)221 void RSRenderEngine::SetColorFilterModeToPaint(Drawing::Brush& paint)
222 {
223     // for test automation
224     if (colorFilterMode_ != ColorFilterMode::COLOR_FILTER_END) {
225         RS_LOGD("RSRenderEngine::SetColorFilterModeToPaint mode:%{public}d", static_cast<int32_t>(colorFilterMode_));
226     }
227     RSBaseRenderUtil::SetColorFilterModeToPaint(colorFilterMode_, paint);
228 }
229 } // namespace Rosen
230 } // namespace OHOS
231