• 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 "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