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