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 = GetFilterTypeString();
92 for (const auto& shaderFilter : shaderFilters_) {
93 switch (shaderFilter->GetShaderFilterType()) {
94 case RSShaderFilter::KAWASE: {
95 auto filter = std::static_pointer_cast<RSKawaseBlurShaderFilter>(shaderFilter);
96 filterString = filterString + filter->GetDescription();
97 break;
98 }
99 case RSShaderFilter::MESA: {
100 auto filter = std::static_pointer_cast<RSMESABlurShaderFilter>(shaderFilter);
101 int radius = filter->GetRadius();
102 filterString = filterString + ", MESA radius: " + std::to_string(radius) + " sigma";
103 break;
104 }
105 case RSShaderFilter::LINEAR_GRADIENT_BLUR: {
106 auto filter4 = std::static_pointer_cast<RSLinearGradientBlurShaderFilter>(shaderFilter);
107 float radius2 = filter4->GetLinearGradientBlurRadius();
108 filterString = filterString + ", radius: " + std::to_string(radius2);
109 break;
110 }
111 default:
112 break;
113 }
114 }
115
116 return filterString;
117 }
118
GetDetailedDescription()119 std::string RSDrawingFilter::GetDetailedDescription()
120 {
121 std::string filterString = GetFilterTypeString();
122 for (const auto& shaderFilter : shaderFilters_) {
123 switch (shaderFilter->GetShaderFilterType()) {
124 case RSShaderFilter::KAWASE: {
125 auto filter = std::static_pointer_cast<RSKawaseBlurShaderFilter>(shaderFilter);
126 filterString = filterString + filter->GetDescription();
127 break;
128 }
129 case RSShaderFilter::GREY: {
130 auto filter2 = std::static_pointer_cast<RSGreyShaderFilter>(shaderFilter);
131 float greyCoefLow = filter2->GetGreyCoefLow();
132 float greyCoefHigh = filter2->GetGreyCoefHigh();
133 filterString = filterString + ", greyCoef1: " + std::to_string(greyCoefLow);
134 filterString = filterString + ", greyCoef2: " + std::to_string(greyCoefHigh);
135 break;
136 }
137 case RSShaderFilter::MESA: {
138 auto filter = std::static_pointer_cast<RSMESABlurShaderFilter>(shaderFilter);
139 filterString = filterString + filter->GetDetailedDescription();
140 break;
141 }
142 case RSShaderFilter::MASK_COLOR: {
143 auto filter3 = std::static_pointer_cast<RSMaskColorShaderFilter>(shaderFilter);
144 int colorMode = filter3->GetColorMode();
145 RSColor maskColor = filter3->GetMaskColor();
146 char maskColorStr[UINT8_MAX] = { 0 };
147 auto ret = memset_s(maskColorStr, UINT8_MAX, 0, UINT8_MAX);
148 if (ret != EOK) {
149 return "Failed to memset_s for maskColorStr, ret=" + std::to_string(ret);
150 }
151 if (sprintf_s(maskColorStr, UINT8_MAX, "%08X", maskColor.AsArgbInt()) != -1) {
152 filterString =
153 filterString + ", maskColor: " + maskColorStr + ", colorMode: " + std::to_string(colorMode);
154 }
155 break;
156 }
157 case RSShaderFilter::LINEAR_GRADIENT_BLUR: {
158 auto filter4 = std::static_pointer_cast<RSLinearGradientBlurShaderFilter>(shaderFilter);
159 float radius2 = filter4->GetLinearGradientBlurRadius();
160 filterString = filterString + ", radius: " + std::to_string(radius2);
161 break;
162 }
163 default:
164 break;
165 }
166 }
167
168 return filterString;
169 }
170
GetFilterTypeString() const171 std::string RSDrawingFilter::GetFilterTypeString() const
172 {
173 auto iter = FILTER_TYPE_MAP.find(RSFilter::type_);
174 std::string filterString = "not found.";
175 if (iter != FILTER_TYPE_MAP.end()) {
176 filterString = iter->second;
177 }
178 return filterString;
179 }
180
GetBrush(float brushAlpha) const181 Drawing::Brush RSDrawingFilter::GetBrush(float brushAlpha) const
182 {
183 Drawing::Brush brush;
184 brush.SetAntiAlias(true);
185 auto imageFilter = ProcessImageFilter(brushAlpha);
186 if (imageFilter) {
187 Drawing::Filter filter;
188 filter.SetImageFilter(imageFilter);
189 brush.SetFilter(filter);
190 }
191 return brush;
192 }
193
CanSkipFrame(float radius)194 bool RSDrawingFilter::CanSkipFrame(float radius)
195 {
196 constexpr float HEAVY_BLUR_THRESHOLD = 25.0f;
197 return radius > HEAVY_BLUR_THRESHOLD;
198 }
199
Hash() const200 uint32_t RSDrawingFilter::Hash() const
201 {
202 auto hash = SkOpts::hash(&imageFilterHash_, sizeof(imageFilterHash_), hash_);
203 return hash;
204 }
205
ShaderHash() const206 uint32_t RSDrawingFilter::ShaderHash() const
207 {
208 return hash_;
209 }
210
ImageHash() const211 uint32_t RSDrawingFilter::ImageHash() const
212 {
213 return imageFilterHash_;
214 }
215
Compose(const std::shared_ptr<RSDrawingFilter> other) const216 std::shared_ptr<RSDrawingFilter> RSDrawingFilter::Compose(const std::shared_ptr<RSDrawingFilter> other) const
217 {
218 std::shared_ptr<RSDrawingFilter> result =
219 std::make_shared<RSDrawingFilter>(imageFilter_, shaderFilters_, imageFilterHash_);
220 result->hash_ = hash_;
221 if (other == nullptr) {
222 return result;
223 }
224 result->imageFilter_ = Drawing::ImageFilter::CreateComposeImageFilter(imageFilter_, other->GetImageFilter());
225 for (auto item : other->GetShaderFilters()) {
226 result->InsertShaderFilter(item);
227 }
228 auto otherShaderHash = other->ShaderHash();
229 auto otherImageHash = other->ImageHash();
230 result->hash_ = SkOpts::hash(&otherShaderHash, sizeof(otherShaderHash), hash_);
231 result->imageFilterHash_ = SkOpts::hash(&otherImageHash, sizeof(otherImageHash), imageFilterHash_);
232 return result;
233 }
234
Compose(const std::shared_ptr<RSShaderFilter> other) const235 std::shared_ptr<RSDrawingFilter> RSDrawingFilter::Compose(const std::shared_ptr<RSShaderFilter> other) const
236 {
237 std::shared_ptr<RSDrawingFilter> result =
238 std::make_shared<RSDrawingFilter>(imageFilter_, shaderFilters_, imageFilterHash_);
239 result->hash_ = hash_;
240 if (other == nullptr) {
241 return result;
242 }
243 result->InsertShaderFilter(other);
244 auto otherHash = other->Hash();
245 result->hash_ = SkOpts::hash(&otherHash, sizeof(otherHash), hash_);
246 return result;
247 }
248
Compose(const std::shared_ptr<Drawing::ImageFilter> other,uint32_t hash) const249 std::shared_ptr<RSDrawingFilter> RSDrawingFilter::Compose(
250 const std::shared_ptr<Drawing::ImageFilter> other, uint32_t hash) const
251 {
252 std::shared_ptr<RSDrawingFilter> result =
253 std::make_shared<RSDrawingFilter>(imageFilter_, shaderFilters_, imageFilterHash_);
254 result->hash_ = hash_;
255 if (other == nullptr) {
256 return result;
257 }
258 result->imageFilter_ = Drawing::ImageFilter::CreateComposeImageFilter(imageFilter_, other);
259 result->imageFilterHash_ = SkOpts::hash(&hash, sizeof(hash), imageFilterHash_);
260 return result;
261 }
262
GetImageFilter() const263 std::shared_ptr<Drawing::ImageFilter> RSDrawingFilter::GetImageFilter() const
264 {
265 return imageFilter_;
266 }
267
SetImageFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter)268 void RSDrawingFilter::SetImageFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter)
269 {
270 imageFilter_ = imageFilter;
271 }
272
GetShaderFilters() const273 std::vector<std::shared_ptr<RSShaderFilter>> RSDrawingFilter::GetShaderFilters() const
274 {
275 return shaderFilters_;
276 }
277
InsertShaderFilter(std::shared_ptr<RSShaderFilter> shaderFilter)278 void RSDrawingFilter::InsertShaderFilter(std::shared_ptr<RSShaderFilter> shaderFilter)
279 {
280 shaderFilters_.emplace_back(shaderFilter);
281 }
282
ProcessImageFilter(float brushAlpha) const283 std::shared_ptr<Drawing::ImageFilter> RSDrawingFilter::ProcessImageFilter(float brushAlpha) const
284 {
285 std::shared_ptr<Drawing::ImageFilter> resFilter = imageFilter_;
286 if (!ROSEN_EQ(brushAlpha, 1.0f)) {
287 Drawing::ColorMatrix alphaMatrix;
288 alphaMatrix.SetScale(1.0f, 1.0f, 1.0f, brushAlpha);
289 std::shared_ptr<Drawing::ColorFilter> alphaFilter =
290 Drawing::ColorFilter::CreateMatrixColorFilter(alphaMatrix, Drawing::Clamp::NO_CLAMP);
291 auto alphaImageFilter = Drawing::ImageFilter::CreateColorFilterImageFilter(*alphaFilter, nullptr);
292 resFilter = resFilter ? Drawing::ImageFilter::CreateComposeImageFilter(alphaImageFilter, resFilter) :
293 alphaImageFilter;
294 }
295 return resFilter;
296 }
297
ApplyColorFilter(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,const Drawing::Rect & src,const Drawing::Rect & dst,float brushAlpha)298 void RSDrawingFilter::ApplyColorFilter(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& image,
299 const Drawing::Rect& src, const Drawing::Rect& dst, float brushAlpha)
300 {
301 if (image == nullptr) {
302 ROSEN_LOGE("RSDrawingFilter::ApplyColorFilter image is nullptr");
303 return;
304 }
305
306 Drawing::Brush brush;
307 std::shared_ptr<Drawing::ImageFilter> resFilter = ProcessImageFilter(brushAlpha);
308 if (resFilter) {
309 Drawing::Filter filter;
310 filter.SetImageFilter(resFilter);
311 brush.SetFilter(filter);
312 }
313 canvas.AttachBrush(brush);
314 canvas.DrawImageRect(*image, src, dst, Drawing::SamplingOptions());
315 canvas.DetachBrush();
316
317 return;
318 }
319
ApplyImageEffect(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,const std::shared_ptr<Drawing::GEVisualEffectContainer> & visualEffectContainer,const DrawImageRectAttributes & attr)320 void RSDrawingFilter::ApplyImageEffect(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& image,
321 const std::shared_ptr<Drawing::GEVisualEffectContainer>& visualEffectContainer,
322 const DrawImageRectAttributes& attr)
323 {
324 auto geRender = std::make_shared<GraphicsEffectEngine::GERender>();
325 if (geRender == nullptr) {
326 ROSEN_LOGE("RSDrawingFilter::DrawImageRect geRender is null");
327 return;
328 }
329 auto outImage = geRender->ApplyImageEffect(canvas, *visualEffectContainer, image, attr.src, attr.src,
330 Drawing::SamplingOptions());
331 if (outImage == nullptr) {
332 ROSEN_LOGE("RSDrawingFilter::DrawImageRect outImage is null");
333 return;
334 }
335 auto brush = GetBrush(attr.brushAlpha);
336 std::shared_ptr<RSShaderFilter> kawaseShaderFilter = GetShaderFilterWithType(RSShaderFilter::KAWASE);
337 if (kawaseShaderFilter != nullptr) {
338 auto tmpFilter = std::static_pointer_cast<RSKawaseBlurShaderFilter>(kawaseShaderFilter);
339 auto radius = tmpFilter->GetRadius();
340
341 static constexpr float epsilon = 0.999f;
342 if (ROSEN_LE(radius, epsilon)) {
343 ApplyColorFilter(canvas, outImage, attr.src, attr.dst, attr.brushAlpha);
344 return;
345 }
346 auto hpsParam = Drawing::HpsBlurParameter(attr.src, attr.dst, radius, saturationForHPS_, brightnessForHPS_);
347 if (RSSystemProperties::GetHpsBlurEnabled() && GetFilterType() == RSFilter::MATERIAL &&
348 HpsBlurFilter::GetHpsBlurFilter().ApplyHpsBlur(canvas, outImage, hpsParam,
349 brush.GetColor().GetAlphaF() * attr.brushAlpha, brush.GetFilter().GetColorFilter())) {
350 RS_OPTIONAL_TRACE_NAME("ApplyHPSBlur " + std::to_string(radius));
351 } else {
352 auto effectContainer = std::make_shared<Drawing::GEVisualEffectContainer>();
353 tmpFilter->GenerateGEVisualEffect(effectContainer);
354 auto blurImage = geRender->ApplyImageEffect(
355 canvas, *effectContainer, outImage, attr.src, attr.src, Drawing::SamplingOptions());
356 if (blurImage == nullptr) {
357 ROSEN_LOGE("RSDrawingFilter::DrawImageRect blurImage is null");
358 return;
359 }
360 canvas.AttachBrush(brush);
361 canvas.DrawImageRect(*blurImage, attr.src, attr.dst, Drawing::SamplingOptions());
362 canvas.DetachBrush();
363 RS_OPTIONAL_TRACE_NAME("ApplyKawaseBlur " + std::to_string(radius));
364 }
365 return;
366 }
367 canvas.AttachBrush(brush);
368 canvas.DrawImageRect(*outImage, attr.src, attr.dst, Drawing::SamplingOptions());
369 canvas.DetachBrush();
370 }
371
PrepareAlphaForOnScreenDraw(RSPaintFilterCanvas & paintFilterCanvas)372 float RSDrawingFilter::PrepareAlphaForOnScreenDraw(RSPaintFilterCanvas& paintFilterCanvas)
373 {
374 // if canvas alpha is 1.0 or 0.0 - result is same
375 float canvasAlpha = paintFilterCanvas.GetAlpha();
376 float newAlpha = 1.0f;
377 if (ROSEN_EQ(canvasAlpha, 1.0f) || ROSEN_EQ(canvasAlpha, 0.0f)) {
378 return newAlpha;
379 }
380 std::shared_ptr<RSShaderFilter> maskColorShaderFilter = GetShaderFilterWithType(RSShaderFilter::MASK_COLOR);
381 if (maskColorShaderFilter != nullptr) {
382 auto maskColorFilter = std::static_pointer_cast<RSMaskColorShaderFilter>(maskColorShaderFilter);
383 float postAlpha = maskColorFilter->GetPostProcessAlpha();
384 newAlpha = (1.0f - postAlpha) / (1.0f - postAlpha * canvasAlpha);
385 }
386 paintFilterCanvas.SetAlpha(1.0f);
387 return newAlpha * canvasAlpha;
388 }
389
DrawImageRectInternal(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> image,const DrawImageRectAttributes & attr)390 void RSDrawingFilter::DrawImageRectInternal(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image> image,
391 const DrawImageRectAttributes& attr)
392 {
393 auto visualEffectContainer = std::make_shared<Drawing::GEVisualEffectContainer>();
394 bool kawaseHpsFilter = false;
395 if (visualEffectContainer == nullptr) {
396 ROSEN_LOGE("RSDrawingFilter::DrawImageRect visualEffectContainer is null");
397 return;
398 }
399 for (const auto& filter : shaderFilters_) {
400 if (filter->GetShaderFilterType() == RSShaderFilter::KAWASE) {
401 kawaseHpsFilter = true;
402 continue;
403 }
404 filter->GenerateGEVisualEffect(visualEffectContainer);
405 }
406 auto brush = GetBrush(attr.brushAlpha);
407 if (attr.discardCanvas && kawaseHpsFilter && ROSEN_EQ(brush.GetColor().GetAlphaF(), 1.0f)) {
408 canvas.Discard();
409 }
410 ApplyImageEffect(canvas, image, visualEffectContainer, attr);
411 }
412
DrawImageRect(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> image,const Drawing::Rect & src,const Drawing::Rect & dst,const DrawImageRectParams params)413 void RSDrawingFilter::DrawImageRect(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image> image,
414 const Drawing::Rect& src, const Drawing::Rect& dst, const DrawImageRectParams params)
415 {
416 float canvasAlpha = canvas.GetAlpha();
417 DrawImageRectAttributes attr = { src, dst, params.discardCanvas, 1.0f };
418 if (params.offscreenDraw || ROSEN_EQ(canvasAlpha, 1.0f) || ROSEN_EQ(canvasAlpha, 0.0f)) {
419 DrawImageRectInternal(canvas, image, attr);
420 return;
421 }
422 // Only RSPaintFilterCanvas can have non-zero alpha stack
423 auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
424 RSAutoCanvasRestore autoCanvasRestore(paintFilterCanvas, RSPaintFilterCanvas::kAlpha);
425 attr.brushAlpha = PrepareAlphaForOnScreenDraw(*paintFilterCanvas);
426 DrawImageRectInternal(canvas, image, attr);
427 }
428
PreProcess(std::shared_ptr<Drawing::Image> & image)429 void RSDrawingFilter::PreProcess(std::shared_ptr<Drawing::Image>& image)
430 {
431 std::for_each(shaderFilters_.begin(), shaderFilters_.end(), [&](auto& filter) {
432 filter->PreProcess(image);
433 });
434 }
435
PostProcess(Drawing::Canvas & canvas)436 void RSDrawingFilter::PostProcess(Drawing::Canvas& canvas)
437 {
438 std::for_each(shaderFilters_.begin(), shaderFilters_.end(), [&](auto& filter) {
439 filter->PostProcess(canvas);
440 });
441 }
442 } // namespace Rosen
443 } // namespace OHOS
444