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 "render/rs_drawing_filter.h"
17 
18 #include <memory>
19 
20 #include "common/rs_optional_trace.h"
21 #include "draw/blend_mode.h"
22 #include "ge_render.h"
23 #include "ge_visual_effect.h"
24 #include "platform/common/rs_log.h"
25 #include "platform/common/rs_system_properties.h"
26 #include "property/rs_properties_painter.h"
27 #include "render/rs_aibar_shader_filter.h"
28 #include "render/rs_grey_shader_filter.h"
29 #include "render/rs_kawase_blur_shader_filter.h"
30 #include "render/rs_mesa_blur_shader_filter.h"
31 #include "render/rs_linear_gradient_blur_shader_filter.h"
32 #include "render/rs_maskcolor_shader_filter.h"
33 #include "src/core/SkOpts.h"
34 
35 namespace OHOS {
36 namespace Rosen {
37 namespace {
38 constexpr int SHADER_FILTERS_SIZE = 10;
39 const std::map<int, std::string> FILTER_TYPE_MAP {
40     { RSFilter::BLUR, "RSBlurFilterBlur" },
41     { RSFilter::MATERIAL, "RSMaterialFilterBlur" },
42     { RSFilter::AIBAR, "RSAIBarFilterBlur" },
43     { RSFilter::LINEAR_GRADIENT_BLUR, "RSLinearGradientBlurFilterBlur" },
44     { RSFilter::MAGNIFIER, "RSMagnifierFilter" },
45     { RSFilter::WATER_RIPPLE, "RSWaterRippleFilter" },
46     { RSFilter::COMPOUND_EFFECT, "CompoundEffect" },
47     { RSFilter::FLY_OUT, "FlyOut" },
48     { RSFilter::DISTORT, "RSDistortionFilter" },
49 };
50 }
RSDrawingFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter,uint32_t hash)51 RSDrawingFilter::RSDrawingFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter, uint32_t hash)
52     : RSFilter(), imageFilter_(imageFilter)
53 {
54     imageFilterHash_ = hash;
55     shaderFilters_.reserve(SHADER_FILTERS_SIZE);
56 }
57 
RSDrawingFilter(std::shared_ptr<RSShaderFilter> shaderFilter)58 RSDrawingFilter::RSDrawingFilter(std::shared_ptr<RSShaderFilter> shaderFilter)
59 {
60     hash_ = shaderFilter->Hash();
61     shaderFilters_.reserve(SHADER_FILTERS_SIZE);
62     shaderFilters_.emplace_back(shaderFilter);
63     imageFilterHash_ = static_cast<uint32_t>(0);
64 }
65 
RSDrawingFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter,std::shared_ptr<RSShaderFilter> shaderFilter,uint32_t hash)66 RSDrawingFilter::RSDrawingFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter,
67     std::shared_ptr<RSShaderFilter> shaderFilter, uint32_t hash) : RSFilter(), imageFilter_(imageFilter)
68 {
69     hash_ = shaderFilter->Hash();
70     imageFilterHash_ = hash;
71     shaderFilters_.reserve(SHADER_FILTERS_SIZE);
72     shaderFilters_.emplace_back(shaderFilter);
73 }
74 
RSDrawingFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter,std::vector<std::shared_ptr<RSShaderFilter>> shaderFilters,uint32_t hash)75 RSDrawingFilter::RSDrawingFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter,
76     std::vector<std::shared_ptr<RSShaderFilter>> shaderFilters, uint32_t hash)
77     : RSFilter(), imageFilter_(imageFilter)
78 {
79     shaderFilters_ = shaderFilters;
80     for (const auto& shaderFilter : shaderFilters_) {
81         uint32_t hash = shaderFilter->Hash();
82         hash_ = SkOpts::hash(&hash, sizeof(hash), hash_);
83     }
84     imageFilterHash_ = hash;
85 }
86 
~RSDrawingFilter()87 RSDrawingFilter::~RSDrawingFilter() {};
88 
GetDescription()89 std::string RSDrawingFilter::GetDescription()
90 {
91     std::string filterString = FILTER_TYPE_MAP.at(RSFilter::type_);
92     for (const auto& shaderFilter : shaderFilters_) {
93         switch (shaderFilter->GetShaderFilterType()) {
94             case RSShaderFilter::KAWASE: {
95                 auto filter = std::static_pointer_cast<RSKawaseBlurShaderFilter>(shaderFilter);
96                 int radius = filter->GetRadius();
97                 filterString = filterString + ", radius: " + std::to_string(radius) + " sigma";
98                 break;
99             }
100             case RSShaderFilter::MESA: {
101                 auto filter = std::static_pointer_cast<RSMESABlurShaderFilter>(shaderFilter);
102                 int radius = filter->GetRadius();
103                 filterString = filterString + ", MESA radius: " + std::to_string(radius) + " sigma";
104                 break;
105             }
106             case RSShaderFilter::LINEAR_GRADIENT_BLUR: {
107                 auto filter4 = std::static_pointer_cast<RSLinearGradientBlurShaderFilter>(shaderFilter);
108                 float radius2 = filter4->GetLinearGradientBlurRadius();
109                 filterString = filterString + ", radius: " + std::to_string(radius2);
110                 break;
111             }
112             default:
113                 break;
114         }
115     }
116 
117     return filterString;
118 }
119 
GetDetailedDescription()120 std::string RSDrawingFilter::GetDetailedDescription()
121 {
122     std::string filterString = FILTER_TYPE_MAP.at(RSFilter::type_);
123     for (const auto& shaderFilter : shaderFilters_) {
124         switch (shaderFilter->GetShaderFilterType()) {
125             case RSShaderFilter::KAWASE: {
126                 auto filter = std::static_pointer_cast<RSKawaseBlurShaderFilter>(shaderFilter);
127                 int radius = filter->GetRadius();
128                 filterString = filterString + ", radius: " + std::to_string(radius) + " sigma";
129                 break;
130             }
131             case RSShaderFilter::GREY: {
132                 auto filter2 = std::static_pointer_cast<RSGreyShaderFilter>(shaderFilter);
133                 float greyCoefLow = filter2->GetGreyCoefLow();
134                 float greyCoefHigh = filter2->GetGreyCoefHigh();
135                 filterString = filterString + ", greyCoef1: " + std::to_string(greyCoefLow);
136                 filterString = filterString + ", greyCoef2: " + std::to_string(greyCoefHigh);
137                 break;
138             }
139             case RSShaderFilter::MESA: {
140                 auto filter = std::static_pointer_cast<RSMESABlurShaderFilter>(shaderFilter);
141                 filterString = filterString + filter->GetDetailedDescription();
142                 break;
143             }
144             case RSShaderFilter::MASK_COLOR: {
145                 auto filter3 = std::static_pointer_cast<RSMaskColorShaderFilter>(shaderFilter);
146                 int colorMode = filter3->GetColorMode();
147                 RSColor maskColor = filter3->GetMaskColor();
148                 char maskColorStr[UINT8_MAX] = { 0 };
149                 auto ret = memset_s(maskColorStr, UINT8_MAX, 0, UINT8_MAX);
150                 if (ret != EOK) {
151                     return "Failed to memset_s for maskColorStr, ret=" + std::to_string(ret);
152                 }
153                 if (sprintf_s(maskColorStr, UINT8_MAX, "%08X", maskColor.AsArgbInt()) != -1) {
154                     filterString =
155                         filterString + ", maskColor: " + maskColorStr + ", colorMode: " + std::to_string(colorMode);
156                 }
157                 break;
158             }
159             case RSShaderFilter::LINEAR_GRADIENT_BLUR: {
160                 auto filter4 = std::static_pointer_cast<RSLinearGradientBlurShaderFilter>(shaderFilter);
161                 float radius2 = filter4->GetLinearGradientBlurRadius();
162                 filterString = filterString + ", radius: " + std::to_string(radius2);
163                 break;
164             }
165             default:
166                 break;
167         }
168     }
169 
170     return filterString;
171 }
172 
GetBrush() const173 Drawing::Brush RSDrawingFilter::GetBrush() const
174 {
175     Drawing::Brush brush;
176     brush.SetAntiAlias(true);
177     Drawing::Filter filter;
178     filter.SetImageFilter(imageFilter_);
179     brush.SetFilter(filter);
180     return brush;
181 }
182 
CanSkipFrame(float radius)183 bool RSDrawingFilter::CanSkipFrame(float radius)
184 {
185     constexpr float HEAVY_BLUR_THRESHOLD = 25.0f;
186     return radius > HEAVY_BLUR_THRESHOLD;
187 }
188 
Hash() const189 uint32_t RSDrawingFilter::Hash() const
190 {
191     auto hash = SkOpts::hash(&imageFilterHash_, sizeof(imageFilterHash_), hash_);
192     return hash;
193 }
194 
ShaderHash() const195 uint32_t RSDrawingFilter::ShaderHash() const
196 {
197     return hash_;
198 }
199 
ImageHash() const200 uint32_t RSDrawingFilter::ImageHash() const
201 {
202     return imageFilterHash_;
203 }
204 
Compose(const std::shared_ptr<RSDrawingFilter> other) const205 std::shared_ptr<RSDrawingFilter> RSDrawingFilter::Compose(const std::shared_ptr<RSDrawingFilter> other) const
206 {
207     std::shared_ptr<RSDrawingFilter> result =
208         std::make_shared<RSDrawingFilter>(imageFilter_, shaderFilters_, imageFilterHash_);
209     result->hash_ = hash_;
210     if (other == nullptr) {
211         return result;
212     }
213     result->imageFilter_ = Drawing::ImageFilter::CreateComposeImageFilter(imageFilter_, other->GetImageFilter());
214     for (auto item : other->GetShaderFilters()) {
215         result->InsertShaderFilter(item);
216     }
217     auto otherShaderHash = other->ShaderHash();
218     auto otherImageHash = other->ImageHash();
219     result->hash_ = SkOpts::hash(&otherShaderHash, sizeof(otherShaderHash), hash_);
220     result->imageFilterHash_ = SkOpts::hash(&otherImageHash, sizeof(otherImageHash), imageFilterHash_);
221     return result;
222 }
223 
Compose(const std::shared_ptr<RSShaderFilter> other) const224 std::shared_ptr<RSDrawingFilter> RSDrawingFilter::Compose(const std::shared_ptr<RSShaderFilter> other) const
225 {
226     std::shared_ptr<RSDrawingFilter> result =
227         std::make_shared<RSDrawingFilter>(imageFilter_, shaderFilters_, imageFilterHash_);
228     result->hash_ = hash_;
229     if (other == nullptr) {
230         return result;
231     }
232     result->InsertShaderFilter(other);
233     auto otherHash = other->Hash();
234     result->hash_ = SkOpts::hash(&otherHash, sizeof(otherHash), hash_);
235     return result;
236 }
237 
Compose(const std::shared_ptr<Drawing::ImageFilter> other,uint32_t hash) const238 std::shared_ptr<RSDrawingFilter> RSDrawingFilter::Compose(
239     const std::shared_ptr<Drawing::ImageFilter> other, uint32_t hash) const
240 {
241     std::shared_ptr<RSDrawingFilter> result =
242         std::make_shared<RSDrawingFilter>(imageFilter_, shaderFilters_, imageFilterHash_);
243     result->hash_ = hash_;
244     if (other == nullptr) {
245         return result;
246     }
247     result->imageFilter_ = Drawing::ImageFilter::CreateComposeImageFilter(imageFilter_, other);
248     result->imageFilterHash_ = SkOpts::hash(&hash, sizeof(hash), imageFilterHash_);
249     return result;
250 }
251 
GetImageFilter() const252 std::shared_ptr<Drawing::ImageFilter> RSDrawingFilter::GetImageFilter() const
253 {
254     return imageFilter_;
255 }
256 
SetImageFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter)257 void RSDrawingFilter::SetImageFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter)
258 {
259     imageFilter_ = imageFilter;
260 }
261 
GetShaderFilters() const262 std::vector<std::shared_ptr<RSShaderFilter>> RSDrawingFilter::GetShaderFilters() const
263 {
264     return shaderFilters_;
265 }
266 
InsertShaderFilter(std::shared_ptr<RSShaderFilter> shaderFilter)267 void RSDrawingFilter::InsertShaderFilter(std::shared_ptr<RSShaderFilter> shaderFilter)
268 {
269     shaderFilters_.emplace_back(shaderFilter);
270 }
271 
ApplyColorFilter(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,const Drawing::Rect & src,const Drawing::Rect & dst)272 void RSDrawingFilter::ApplyColorFilter(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& image,
273     const Drawing::Rect& src, const Drawing::Rect& dst)
274 {
275     if (image == nullptr) {
276         ROSEN_LOGE("RSDrawingFilter::ApplyColorFilter image is null");
277         return;
278     }
279 
280     Drawing::Brush brush;
281     if (imageFilter_) {
282         Drawing::Filter filter;
283         filter.SetImageFilter(imageFilter_);
284         brush.SetFilter(filter);
285     }
286     canvas.AttachBrush(brush);
287     canvas.DrawImageRect(*image, src, dst, Drawing::SamplingOptions());
288     canvas.DetachBrush();
289 
290     return;
291 }
292 
DrawImageRect(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> image,const Drawing::Rect & src,const Drawing::Rect & dst)293 void RSDrawingFilter::DrawImageRect(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image> image,
294     const Drawing::Rect& src, const Drawing::Rect& dst)
295 {
296     auto visualEffectContainer = std::make_shared<Drawing::GEVisualEffectContainer>();
297     for (const auto& filter : shaderFilters_) {
298         if (filter->GetShaderFilterType() == RSShaderFilter::KAWASE) {
299             continue;
300         }
301         filter->GenerateGEVisualEffect(visualEffectContainer);
302     };
303     auto geRender = std::make_shared<GraphicsEffectEngine::GERender>();
304     auto outImage = geRender->ApplyImageEffect(
305         canvas, *visualEffectContainer, image, src, src, Drawing::SamplingOptions());
306     if (outImage == nullptr) {
307         ROSEN_LOGE("RSDrawingFilter::DrawImageRect outImage is null");
308         return;
309     }
310     auto brush = GetBrush();
311     std::shared_ptr<RSShaderFilter> kawaseShaderFilter = GetShaderFilterWithType(RSShaderFilter::KAWASE);
312     if (kawaseShaderFilter != nullptr) {
313         auto tmpFilter = std::static_pointer_cast<RSKawaseBlurShaderFilter>(kawaseShaderFilter);
314         auto radius = tmpFilter->GetRadius();
315 
316         static constexpr float epsilon = 0.999f;
317         if (ROSEN_LE(radius, epsilon)) {
318             ApplyColorFilter(canvas, outImage, src, dst);
319             return;
320         }
321         auto hpsParam = Drawing::HpsBlurParameter(src, dst, radius, saturationForHPS_, brightnessForHPS_);
322         if (RSSystemProperties::GetHpsBlurEnabled() && GetFilterType() == RSFilter::MATERIAL &&
323             HpsBlurFilter::GetHpsBlurFilter().ApplyHpsBlur(canvas, outImage, hpsParam, brush.GetColor().GetAlphaF())) {
324             RS_OPTIONAL_TRACE_NAME("ApplyHPSBlur " + std::to_string(radius));
325         } else {
326             auto effectContainer = std::make_shared<Drawing::GEVisualEffectContainer>();
327             tmpFilter->GenerateGEVisualEffect(effectContainer);
328             auto blurImage = geRender->ApplyImageEffect(
329                 canvas, *effectContainer, outImage, src, src, Drawing::SamplingOptions());
330             if (blurImage == nullptr) {
331                 ROSEN_LOGE("RSDrawingFilter::DrawImageRect blurImage is null");
332                 return;
333             }
334             canvas.AttachBrush(brush);
335             canvas.DrawImageRect(*blurImage, src, dst, Drawing::SamplingOptions());
336             canvas.DetachBrush();
337             RS_OPTIONAL_TRACE_NAME("ApplyKawaseBlur " + std::to_string(radius));
338         }
339         return;
340     }
341     canvas.AttachBrush(brush);
342     canvas.DrawImageRect(*outImage, src, dst, Drawing::SamplingOptions());
343     canvas.DetachBrush();
344 }
345 
PreProcess(std::shared_ptr<Drawing::Image> & image)346 void RSDrawingFilter::PreProcess(std::shared_ptr<Drawing::Image>& image)
347 {
348     std::for_each(shaderFilters_.begin(), shaderFilters_.end(), [&](auto& filter) {
349         filter->PreProcess(image);
350     });
351 }
352 
PostProcess(Drawing::Canvas & canvas)353 void RSDrawingFilter::PostProcess(Drawing::Canvas& canvas)
354 {
355     std::for_each(shaderFilters_.begin(), shaderFilters_.end(), [&](auto& filter) {
356         filter->PostProcess(canvas);
357     });
358 }
359 } // namespace Rosen
360 } // namespace OHOS
361