• 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 "ge_render.h"
21 #include "ge_visual_effect.h"
22 #include "ge_visual_effect_impl.h"
23 #include "common/rs_optional_trace.h"
24 #include "draw/blend_mode.h"
25 #include "effect/rs_render_filter_base.h"
26 #include "platform/common/rs_log.h"
27 #include "platform/common/rs_system_properties.h"
28 #include "property/rs_properties_painter.h"
29 #include "render/rs_render_aibar_filter.h"
30 #include "render/rs_render_grey_filter.h"
31 #include "render/rs_render_kawase_blur_filter.h"
32 #include "render/rs_render_light_blur_filter.h"
33 #include "render/rs_render_linear_gradient_blur_filter.h"
34 #include "render/rs_render_maskcolor_filter.h"
35 #include "render/rs_render_mesa_blur_filter.h"
36 
37 #include "rs_profiler.h"
38 #ifdef USE_M133_SKIA
39 #include "src/core/SkChecksum.h"
40 #else
41 #include "render/rs_shader_filter.h"
42 #include "src/core/SkOpts.h"
43 #endif
44 
45 namespace OHOS {
46 namespace Rosen {
47 namespace {
48 constexpr int SHADER_FILTERS_SIZE = 10;
49 const std::map<int, std::string> FILTER_TYPE_MAP {
50     { RSFilter::BLUR, "RSBlurFilterBlur" },
51     { RSFilter::MATERIAL, "RSMaterialFilterBlur" },
52     { RSFilter::AIBAR, "RSAIBarFilterBlur" },
53     { RSFilter::LINEAR_GRADIENT_BLUR, "RSLinearGradientBlurFilterBlur" },
54     { RSFilter::MAGNIFIER, "RSMagnifierFilter" },
55     { RSFilter::WATER_RIPPLE, "RSWaterRippleFilter" },
56     { RSFilter::COMPOUND_EFFECT, "CompoundEffect" },
57     { RSFilter::FLY_OUT, "FlyOut" },
58     { RSFilter::DISTORT, "RSDistortionFilter" },
59     { RSFilter::EDGE_LIGHT, "EdgeLight" },
60     { RSFilter::DISPERSION, "Dispersion" },
61     { RSFilter::COLOR_GRADIENT, "ColorGradient" },
62 };
63 }
64 
CanApplyColorFilterInsteadOfBlur(float radius)65 static bool CanApplyColorFilterInsteadOfBlur(float radius)
66 {
67     static constexpr float epsilon = 0.999f;
68     return ROSEN_LE(radius, epsilon);
69 }
70 
RSDrawingFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter,uint32_t hash)71 RSDrawingFilter::RSDrawingFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter, uint32_t hash)
72     : RSFilter(), imageFilter_(imageFilter)
73 {
74     imageFilterHash_ = hash;
75     shaderFilters_.reserve(SHADER_FILTERS_SIZE);
76 }
77 
RSDrawingFilter(std::shared_ptr<RSRenderFilterParaBase> shaderFilter)78 RSDrawingFilter::RSDrawingFilter(std::shared_ptr<RSRenderFilterParaBase> shaderFilter)
79 {
80     hash_ = shaderFilter->Hash();
81     shaderFilters_.reserve(SHADER_FILTERS_SIZE);
82     shaderFilters_.emplace_back(shaderFilter);
83     imageFilterHash_ = static_cast<uint32_t>(0);
84 }
85 
RSDrawingFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter,std::shared_ptr<RSRenderFilterParaBase> shaderFilter,uint32_t hash)86 RSDrawingFilter::RSDrawingFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter,
87     std::shared_ptr<RSRenderFilterParaBase> shaderFilter, uint32_t hash) : RSFilter(), imageFilter_(imageFilter)
88 {
89     hash_ = shaderFilter->Hash();
90     imageFilterHash_ = hash;
91     shaderFilters_.reserve(SHADER_FILTERS_SIZE);
92     shaderFilters_.emplace_back(shaderFilter);
93 }
94 
RSDrawingFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter,std::vector<std::shared_ptr<RSRenderFilterParaBase>> shaderFilters,uint32_t hash)95 RSDrawingFilter::RSDrawingFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter,
96     std::vector<std::shared_ptr<RSRenderFilterParaBase>> shaderFilters, uint32_t hash)
97     : RSFilter(), imageFilter_(imageFilter)
98 {
99     shaderFilters_ = shaderFilters;
100     for (const auto& shaderFilter : shaderFilters_) {
101         uint32_t hash = shaderFilter->Hash();
102 #ifdef USE_M133_SKIA
103         const auto hashFunc = SkChecksum::Hash32;
104 #else
105         const auto hashFunc = SkOpts::hash;
106 #endif
107         hash_ = hashFunc(&hash, sizeof(hash), hash_);
108     }
109     imageFilterHash_ = hash;
110 }
111 
~RSDrawingFilter()112 RSDrawingFilter::~RSDrawingFilter() {};
113 
GetDescription()114 std::string RSDrawingFilter::GetDescription()
115 {
116     std::string filterString = GetFilterTypeString();
117     for (const auto& shaderFilter : shaderFilters_) {
118         if (shaderFilter == nullptr) {
119             continue;
120         }
121         switch (shaderFilter->GetType()) {
122             case RSUIFilterType::KAWASE: {
123                 auto filter = std::static_pointer_cast<RSKawaseBlurShaderFilter>(shaderFilter);
124                 filter->GetDescription(filterString);
125                 break;
126             }
127             case RSUIFilterType::MESA: {
128                 auto filter = std::static_pointer_cast<RSMESABlurShaderFilter>(shaderFilter);
129                 int radius = filter->GetRadius();
130                 filterString = filterString + ", MESA radius: " + std::to_string(radius) + " sigma";
131                 break;
132             }
133             case RSUIFilterType::LINEAR_GRADIENT_BLUR: {
134                 auto filter4 = std::static_pointer_cast<RSLinearGradientBlurShaderFilter>(shaderFilter);
135                 float radius2 = filter4->GetLinearGradientBlurRadius();
136                 filterString = filterString + ", radius: " + std::to_string(radius2);
137                 break;
138             }
139             default:
140                 break;
141         }
142     }
143 
144     return filterString;
145 }
146 
GetDetailedDescription()147 std::string RSDrawingFilter::GetDetailedDescription()
148 {
149     std::string filterString = GetFilterTypeString();
150     for (const auto& shaderFilter : shaderFilters_) {
151         switch (shaderFilter->GetType()) {
152             case RSUIFilterType::KAWASE: {
153                 auto filter = std::static_pointer_cast<RSKawaseBlurShaderFilter>(shaderFilter);
154                 filter->GetDescription(filterString);
155                 break;
156             }
157             case RSUIFilterType::GREY: {
158                 auto filter2 = std::static_pointer_cast<RSGreyShaderFilter>(shaderFilter);
159                 float greyCoefLow = filter2->GetGreyCoefLow();
160                 float greyCoefHigh = filter2->GetGreyCoefHigh();
161                 filterString = filterString + ", greyCoef1: " + std::to_string(greyCoefLow);
162                 filterString = filterString + ", greyCoef2: " + std::to_string(greyCoefHigh);
163                 break;
164             }
165             case RSUIFilterType::MESA: {
166                 auto filter = std::static_pointer_cast<RSMESABlurShaderFilter>(shaderFilter);
167                 filterString = filterString + filter->GetDetailedDescription();
168                 break;
169             }
170             case RSUIFilterType::MASK_COLOR: {
171                 auto filter3 = std::static_pointer_cast<RSMaskColorShaderFilter>(shaderFilter);
172                 int colorMode = filter3->GetColorMode();
173                 RSColor maskColor = filter3->GetMaskColor();
174                 char maskColorStr[UINT8_MAX] = { 0 };
175                 auto ret = memset_s(maskColorStr, UINT8_MAX, 0, UINT8_MAX);
176                 if (ret != EOK) {
177                     return "Failed to memset_s for maskColorStr, ret=" + std::to_string(ret);
178                 }
179                 if (sprintf_s(maskColorStr, UINT8_MAX, "%08X", maskColor.AsArgbInt()) != -1) {
180                     filterString =
181                         filterString + ", maskColor: " + maskColorStr + ", colorMode: " + std::to_string(colorMode);
182                 }
183                 break;
184             }
185             case RSUIFilterType::LINEAR_GRADIENT_BLUR: {
186                 auto filter4 = std::static_pointer_cast<RSLinearGradientBlurShaderFilter>(shaderFilter);
187                 float radius2 = filter4->GetLinearGradientBlurRadius();
188                 filterString = filterString + ", radius: " + std::to_string(radius2);
189                 break;
190             }
191             default:
192                 break;
193         }
194     }
195 
196     return filterString;
197 }
198 
GetFilterTypeString() const199 std::string RSDrawingFilter::GetFilterTypeString() const
200 {
201     auto iter = FILTER_TYPE_MAP.find(RSFilter::type_);
202     std::string filterString = "not found.";
203     if (iter != FILTER_TYPE_MAP.end()) {
204         filterString = iter->second;
205     }
206     return filterString;
207 }
208 
GetBrush(float brushAlpha) const209 Drawing::Brush RSDrawingFilter::GetBrush(float brushAlpha) const
210 {
211     Drawing::Brush brush;
212     brush.SetAntiAlias(true);
213     auto imageFilter = ProcessImageFilter(brushAlpha);
214     if (imageFilter) {
215         Drawing::Filter filter;
216         filter.SetImageFilter(imageFilter);
217         brush.SetFilter(filter);
218     }
219     return brush;
220 }
221 
GenerateAndUpdateGEVisualEffect()222 void RSDrawingFilter::GenerateAndUpdateGEVisualEffect()
223 {
224     visualEffectContainer_ = std::make_shared<Drawing::GEVisualEffectContainer>();
225     for (const auto& filter : shaderFilters_) {
226         if (filter->GetType() == RSUIFilterType::KAWASE) {
227             continue;
228         }
229         filter->GenerateGEVisualEffect(visualEffectContainer_);
230     }
231     if (!renderFilter_) {
232         return;
233     }
234     RSUIFilterHelper::GenerateGEVisualEffect(renderFilter_);
235     RSUIFilterHelper::UpdateToGEContainer(renderFilter_, visualEffectContainer_);
236 }
237 
SetGeometry(Drawing::Canvas & canvas,float geoWidth,float geoHeight)238 void RSDrawingFilter::SetGeometry(Drawing::Canvas& canvas, float geoWidth, float geoHeight)
239 {
240     if (visualEffectContainer_) {
241         visualEffectContainer_->SetGeometry(canvas, geoWidth, geoHeight);
242     }
243 }
244 
SetDisplayHeadroom(float headroom)245 void RSDrawingFilter::SetDisplayHeadroom(float headroom)
246 {
247     if (visualEffectContainer_) {
248         visualEffectContainer_->SetDisplayHeadroom(headroom);
249     }
250 }
251 
CanSkipFrame(float radius)252 bool RSDrawingFilter::CanSkipFrame(float radius)
253 {
254     constexpr float HEAVY_BLUR_THRESHOLD = 25.0f;
255     return radius > HEAVY_BLUR_THRESHOLD;
256 }
257 
OnSync()258 void RSDrawingFilter::OnSync()
259 {
260     if (renderFilter_) {
261         renderFilter_->OnSync();
262     }
263     GenerateAndUpdateGEVisualEffect();
264 }
265 
Hash() const266 uint32_t RSDrawingFilter::Hash() const
267 {
268 #ifdef USE_M133_SKIA
269     const auto hashFunc = SkChecksum::Hash32;
270 #else
271     const auto hashFunc = SkOpts::hash;
272 #endif
273     auto hash = hashFunc(&imageFilterHash_, sizeof(imageFilterHash_), hash_);
274     hash = hashFunc(&renderFilterHash_, sizeof(renderFilterHash_), hash);
275     return hash;
276 }
277 
ShaderHash() const278 uint32_t RSDrawingFilter::ShaderHash() const
279 {
280     return hash_;
281 }
282 
ImageHash() const283 uint32_t RSDrawingFilter::ImageHash() const
284 {
285     return imageFilterHash_;
286 }
287 
RenderFilterHash() const288 uint32_t RSDrawingFilter::RenderFilterHash() const
289 {
290     return renderFilterHash_;
291 }
292 
Compose(const std::shared_ptr<RSRenderFilterParaBase> other) const293 std::shared_ptr<RSDrawingFilter> RSDrawingFilter::Compose(const std::shared_ptr<RSRenderFilterParaBase> other) const
294 {
295     std::shared_ptr<RSDrawingFilter> result =
296         std::make_shared<RSDrawingFilter>(imageFilter_, shaderFilters_, imageFilterHash_);
297     result->hash_ = hash_;
298     if (other == nullptr) {
299         return result;
300     }
301     result->InsertShaderFilter(other);
302     auto otherHash = other->Hash();
303 #ifdef USE_M133_SKIA
304     const auto hashFunc = SkChecksum::Hash32;
305 #else
306     const auto hashFunc = SkOpts::hash;
307 #endif
308     result->hash_ = hashFunc(&otherHash, sizeof(otherHash), hash_);
309     return result;
310 }
311 
Compose(const std::shared_ptr<Drawing::ImageFilter> other,uint32_t hash) const312 std::shared_ptr<RSDrawingFilter> RSDrawingFilter::Compose(
313     const std::shared_ptr<Drawing::ImageFilter> other, uint32_t hash) const
314 {
315     std::shared_ptr<RSDrawingFilter> result =
316         std::make_shared<RSDrawingFilter>(imageFilter_, shaderFilters_, imageFilterHash_);
317     result->hash_ = hash_;
318     if (other == nullptr) {
319         return result;
320     }
321     result->imageFilter_ = Drawing::ImageFilter::CreateComposeImageFilter(imageFilter_, other);
322 #ifdef USE_M133_SKIA
323     const auto hashFunc = SkChecksum::Hash32;
324 #else
325     const auto hashFunc = SkOpts::hash;
326 #endif
327     result->imageFilterHash_ = hashFunc(&hash, sizeof(hash), imageFilterHash_);
328     return result;
329 }
330 
SetNGRenderFilter(std::shared_ptr<RSNGRenderFilterBase> filter)331 void RSDrawingFilter::SetNGRenderFilter(std::shared_ptr<RSNGRenderFilterBase> filter)
332 {
333     renderFilter_ = filter;
334 
335     if (!renderFilterHash_) {
336         renderFilterHash_ = 0;
337         return;
338     }
339     renderFilterHash_ = renderFilter_->CalculateHash();
340 }
341 
GetImageFilter() const342 std::shared_ptr<Drawing::ImageFilter> RSDrawingFilter::GetImageFilter() const
343 {
344     return imageFilter_;
345 }
346 
SetImageFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter)347 void RSDrawingFilter::SetImageFilter(std::shared_ptr<Drawing::ImageFilter> imageFilter)
348 {
349     imageFilter_ = imageFilter;
350 }
351 
GetShaderFilters() const352 std::vector<std::shared_ptr<RSRenderFilterParaBase>> RSDrawingFilter::GetShaderFilters() const
353 {
354     return shaderFilters_;
355 }
356 
InsertShaderFilter(std::shared_ptr<RSRenderFilterParaBase> shaderFilter)357 void RSDrawingFilter::InsertShaderFilter(std::shared_ptr<RSRenderFilterParaBase> shaderFilter)
358 {
359     shaderFilters_.emplace_back(shaderFilter);
360 }
361 
ProcessImageFilter(float brushAlpha) const362 std::shared_ptr<Drawing::ImageFilter> RSDrawingFilter::ProcessImageFilter(float brushAlpha) const
363 {
364     std::shared_ptr<Drawing::ImageFilter> resFilter = imageFilter_;
365     if (!ROSEN_EQ(brushAlpha, 1.0f)) {
366         Drawing::ColorMatrix alphaMatrix;
367         alphaMatrix.SetScale(1.0f, 1.0f, 1.0f, brushAlpha);
368         std::shared_ptr<Drawing::ColorFilter> alphaFilter =
369             Drawing::ColorFilter::CreateMatrixColorFilter(alphaMatrix, Drawing::Clamp::NO_CLAMP);
370         auto alphaImageFilter = Drawing::ImageFilter::CreateColorFilterImageFilter(*alphaFilter, nullptr);
371         resFilter = resFilter ? Drawing::ImageFilter::CreateComposeImageFilter(alphaImageFilter, resFilter) :
372             alphaImageFilter;
373     }
374     return resFilter;
375 }
376 
ApplyColorFilter(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,const Drawing::Rect & src,const Drawing::Rect & dst,float brushAlpha)377 void RSDrawingFilter::ApplyColorFilter(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& image,
378     const Drawing::Rect& src, const Drawing::Rect& dst, float brushAlpha)
379 {
380     if (image == nullptr) {
381         ROSEN_LOGE("RSDrawingFilter::ApplyColorFilter image is nullptr");
382         return;
383     }
384 
385     Drawing::Brush brush;
386     std::shared_ptr<Drawing::ImageFilter> resFilter = ProcessImageFilter(brushAlpha);
387     if (resFilter) {
388         Drawing::Filter filter;
389         filter.SetImageFilter(resFilter);
390         brush.SetFilter(filter);
391     }
392     canvas.AttachBrush(brush);
393     canvas.DrawImageRect(*image, src, dst, Drawing::SamplingOptions());
394     canvas.DetachBrush();
395 
396     return;
397 }
398 
ApplyImageEffectWithLightBlur(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,const DrawImageRectAttributes & attr,const Drawing::Brush & brush)399 bool RSDrawingFilter::ApplyImageEffectWithLightBlur(Drawing::Canvas& canvas,
400     const std::shared_ptr<Drawing::Image>& image, const DrawImageRectAttributes& attr, const Drawing::Brush& brush)
401 {
402     if (image == nullptr) {
403         return false;
404     }
405     auto lightBlurShaderFilter = GetShaderFilterWithType(RSUIFilterType::LIGHT_BLUR);
406     if (lightBlurShaderFilter == nullptr) {
407         return false;
408     }
409     auto tmpFilter = std::static_pointer_cast<RSLightBlurShaderFilter>(lightBlurShaderFilter);
410     if (CanApplyColorFilterInsteadOfBlur(tmpFilter->GetRadius())) {
411         ApplyColorFilter(canvas, image, attr.src, attr.dst, attr.brushAlpha);
412         return true;
413     }
414     RS_OPTIONAL_TRACE_NAME("ApplyLightBlur width: " + std::to_string(attr.dst.GetWidth()) +
415         ", height: " + std::to_string(attr.dst.GetHeight()));
416     LightBlurParameter para { attr.src, attr.dst, brush };
417     tmpFilter->ApplyLightBlur(canvas, image, para);
418     RS_PROFILER_ADD_LIGHT_BLUR_METRICS(static_cast<uint32_t>(image->GetWidth() * image->GetHeight()));
419     return true;
420 }
421 
IsHpsBlurApplied(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & outImage,const DrawImageRectAttributes & attr,const Drawing::Brush & brush,float radius)422 bool RSDrawingFilter::IsHpsBlurApplied(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& outImage,
423     const DrawImageRectAttributes& attr, const Drawing::Brush& brush, float radius)
424 {
425     if (RSSystemProperties::GetHpsBlurEnabled() && GetFilterType() == RSFilter::MATERIAL) {
426         auto hpsParam = Drawing::HpsBlurParameter(attr.src, attr.dst, radius, saturationForHPS_, brightnessForHPS_);
427         RSColor maskColorForHPS = RSColor();
428         if (ROSEN_EQ(attr.brushAlpha, 1.0f)) {
429             auto maskColorShaderFilter = GetShaderFilterWithType(RSUIFilterType::MASK_COLOR);
430             if (maskColorShaderFilter != nullptr) {
431                 auto maskColorFilter = std::static_pointer_cast<RSMaskColorShaderFilter>(maskColorShaderFilter);
432                 maskColorForHPS = maskColorFilter->GetMaskColor();
433             }
434         }
435         bool isHpsBlurApplied = HpsBlurFilter::GetHpsBlurFilter().ApplyHpsBlur(canvas, outImage, hpsParam,
436             brush.GetColor().GetAlphaF() * attr.brushAlpha, brush.GetFilter().GetColorFilter(), maskColorForHPS);
437         if (isHpsBlurApplied) {
438             canSkipMaskColor_ = maskColorForHPS != RSColor();
439         }
440         return isHpsBlurApplied;
441     }
442     return false;
443 }
444 
ProfilerLogImageEffect(std::shared_ptr<Drawing::GEVisualEffectContainer> visualEffectContainer,const std::shared_ptr<Drawing::Image> & image,const Drawing::Rect & src,const std::shared_ptr<Drawing::Image> & outImage)445 void RSDrawingFilter::ProfilerLogImageEffect(std::shared_ptr<Drawing::GEVisualEffectContainer> visualEffectContainer,
446     const std::shared_ptr<Drawing::Image>& image, const Drawing::Rect& src,
447     const std::shared_ptr<Drawing::Image>& outImage)
448 {
449     if (!visualEffectContainer) {
450         return;
451     }
452     if (!RS_PROFILER_IS_RECORDING_MODE()) {
453         return;
454     }
455     for (auto vef : visualEffectContainer->GetFilters()) {
456         auto ve = vef->GetImpl();
457         switch (ve->GetFilterType()) {
458             case Drawing::GEVisualEffectImpl::FilterType::KAWASE_BLUR: {
459                 RS_PROFILER_LOG_SHADER_CALL("KAWASE_BLUR", image, src, outImage);
460                 break;
461             }
462             case Drawing::GEVisualEffectImpl::FilterType::MESA_BLUR: {
463                 RS_PROFILER_LOG_SHADER_CALL("MESA_BLUR", image, src, outImage);
464                 break;
465             }
466             case Drawing::GEVisualEffectImpl::FilterType::AIBAR: {
467                 RS_PROFILER_LOG_SHADER_CALL("AIBAR", image, src, outImage);
468                 break;
469             }
470             case Drawing::GEVisualEffectImpl::FilterType::GREY: {
471                 RS_PROFILER_LOG_SHADER_CALL("GREY", image, src, outImage);
472                 break;
473             }
474             case Drawing::GEVisualEffectImpl::FilterType::LINEAR_GRADIENT_BLUR: {
475                 RS_PROFILER_LOG_SHADER_CALL("LINEAR_GRADIENT_BLUR", image, src, outImage);
476                 break;
477             }
478             case Drawing::GEVisualEffectImpl::FilterType::MAGNIFIER: {
479                 RS_PROFILER_LOG_SHADER_CALL("MAGNIFIER", image, src, outImage);
480                 break;
481             }
482             case Drawing::GEVisualEffectImpl::FilterType::WATER_RIPPLE: {
483                 RS_PROFILER_LOG_SHADER_CALL("WATER_RIPPLE", image, src, outImage);
484                 break;
485             }
486             default:
487                 break;
488         }
489     }
490 }
491 
ApplyHpsImageEffect(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,std::shared_ptr<Drawing::Image> & outImage,const DrawImageRectAttributes & attr,Drawing::Brush & brush)492 bool RSDrawingFilter::ApplyHpsImageEffect(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& image,
493     std::shared_ptr<Drawing::Image>& outImage, const DrawImageRectAttributes& attr, Drawing::Brush& brush)
494 {
495     canSkipMaskColor_ = false;
496     auto geRender = std::make_shared<GraphicsEffectEngine::GERender>();
497     auto hpsVisualEffectContainer = std::make_shared<Drawing::GEVisualEffectContainer>();
498     for (const auto& filter : shaderFilters_) {
499         filter->GenerateGEVisualEffect(hpsVisualEffectContainer);
500     }
501     RSColor maskColorForHPS = RSColor();
502     // if alpha equal 1.0, apply maskcolor
503     if (ROSEN_EQ(attr.brushAlpha, 1.0f)) {
504         auto maskColorShaderFilter = GetShaderFilterWithType(RSUIFilterType::MASK_COLOR);
505         if (maskColorShaderFilter != nullptr) {
506             auto maskColorFilter = std::static_pointer_cast<RSMaskColorShaderFilter>(maskColorShaderFilter);
507             maskColorForHPS = maskColorFilter->GetMaskColor();
508         }
509     }
510     auto maskColor = maskColorForHPS.AsArgbInt();
511     GraphicsEffectEngine::GERender::HpsGEImageEffectContext context = {
512         image, attr.src, attr.dst, Drawing::SamplingOptions(), true, brush.GetColor().GetAlphaF() * attr.brushAlpha,
513         brush.GetFilter().GetColorFilter(), maskColor, saturationForHPS_, brightnessForHPS_};
514 
515     bool kawaseHpsProcess = geRender->ApplyHpsGEImageEffect(canvas, *hpsVisualEffectContainer,
516         context, outImage, brush);
517     if (outImage == nullptr) {
518         ROSEN_LOGD("RSDrawingFilter::ApplyHpsImageEffect ApplyHpsGEEffect failed");
519     }
520     if (kawaseHpsProcess) {
521         canSkipMaskColor_ = maskColorForHPS != RgbPalette::Transparent();
522     }
523     return kawaseHpsProcess;
524 }
525 
DrawKawaseEffect(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & outImage,const DrawImageRectAttributes & attr,const Drawing::Brush & brush,std::shared_ptr<RSRenderFilterParaBase> & kawaseShaderFilter)526 void RSDrawingFilter::DrawKawaseEffect(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& outImage,
527     const DrawImageRectAttributes& attr, const Drawing::Brush& brush,
528     std::shared_ptr<RSRenderFilterParaBase>& kawaseShaderFilter)
529 {
530     auto effectContainer = std::make_shared<Drawing::GEVisualEffectContainer>();
531     auto tmpFilter = std::static_pointer_cast<RSKawaseBlurShaderFilter>(kawaseShaderFilter);
532     tmpFilter->GenerateGEVisualEffect(effectContainer);
533     auto geRender = std::make_shared<GraphicsEffectEngine::GERender>();
534     auto blurImage = geRender->ApplyImageEffect(
535         canvas, *effectContainer, outImage, attr.src, attr.src, Drawing::SamplingOptions());
536     if (blurImage == nullptr) {
537         ROSEN_LOGE("RSDrawingFilter::DrawImageRect blurImage is null");
538         return;
539     }
540     RS_PROFILER_ADD_KAWASE_BLUR_METRICS(static_cast<uint32_t>(outImage->GetWidth() * outImage->GetHeight()));
541     canvas.AttachBrush(brush);
542     canvas.DrawImageRect(*blurImage, attr.src, attr.dst, Drawing::SamplingOptions());
543     canvas.DetachBrush();
544     RS_OPTIONAL_TRACE_NAME("ApplyKawaseBlur " + std::to_string(tmpFilter->GetRadius()));
545 }
546 
ApplyImageEffect(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,const std::shared_ptr<Drawing::GEVisualEffectContainer> & visualEffectContainer,const DrawImageRectAttributes & attr)547 void RSDrawingFilter::ApplyImageEffect(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image>& image,
548     const std::shared_ptr<Drawing::GEVisualEffectContainer>& visualEffectContainer,
549     const DrawImageRectAttributes& attr)
550 {
551     auto geRender = std::make_shared<GraphicsEffectEngine::GERender>();
552     if (geRender == nullptr) {
553         ROSEN_LOGE("RSDrawingFilter::DrawImageRect geRender is null");
554         return;
555     }
556     std::shared_ptr<Drawing::Image> outImage = nullptr;
557     auto brush = GetBrush(attr.brushAlpha);
558     /*
559      * When calling ApplyHpsImageEffect(),
560        if outImage == nullptr means:
561            HPS draw shaderFilters_ fail, and func will return false,
562        if outImage != nullptr and return true means:
563            shaderFilters_ contain Kawase or Mesa and HPS draw shaderFilters_ succ,
564        if outImage != nullptr and return false means:
565            shaderFilters_ not contain Kawase and Mesa and HPS draw shaderFilters_ succ.
566      * Why are visualEffectContainer NOT used when calling ApplyHpsImageEffect()?
567        Due to compatibility issues with HPS 1.0, Kawase filter is skipped when generating visualEffectContainer
568        in RSDrawingFilter::DrawImageRectInternal() and applied later in the following lines. If calling HPS
569        successfully, it will return, skipping the following lines. Therefore, visualEffectContainer must be regenerated
570        in ApplyHpsImageEffect instead of passing visualEffectContainer to get full visualEffectContainer.
571      */
572     if (ApplyHpsImageEffect(canvas, image, outImage, attr, brush)) {
573         return;
574     }
575     if (outImage == nullptr) {
576         outImage = geRender->ApplyImageEffect(canvas, *visualEffectContainer, image, attr.src, attr.src,
577             Drawing::SamplingOptions());
578 
579         ProfilerLogImageEffect(visualEffectContainer, image, attr.src, outImage);
580 
581         if (outImage == nullptr) {
582             ROSEN_LOGE("RSDrawingFilter::DrawImageRect outImage is null");
583             return;
584         }
585     }
586     if (ApplyImageEffectWithLightBlur(canvas, outImage, attr, brush)) {
587         return;
588     }
589 
590     auto kawaseShaderFilter = GetShaderFilterWithType(RSUIFilterType::KAWASE);
591     if (kawaseShaderFilter != nullptr) {
592         auto tmpFilter = std::static_pointer_cast<RSKawaseBlurShaderFilter>(kawaseShaderFilter);
593         auto radius = tmpFilter->GetRadius();
594         if (CanApplyColorFilterInsteadOfBlur(radius)) {
595             ApplyColorFilter(canvas, outImage, attr.src, attr.dst, attr.brushAlpha);
596             return;
597         }
598         canSkipMaskColor_ = false;
599         if (IsHpsBlurApplied(canvas, outImage, attr, brush, radius)) {
600             RS_OPTIONAL_TRACE_NAME("ApplyHPSBlur " + std::to_string(radius));
601         } else {
602             DrawKawaseEffect(canvas, outImage, attr, brush, kawaseShaderFilter);
603         }
604         return;
605     }
606     canvas.AttachBrush(brush);
607     canvas.DrawImageRect(*outImage, attr.src, attr.dst, Drawing::SamplingOptions());
608     canvas.DetachBrush();
609 }
610 
PrepareAlphaForOnScreenDraw(RSPaintFilterCanvas & paintFilterCanvas)611 float RSDrawingFilter::PrepareAlphaForOnScreenDraw(RSPaintFilterCanvas& paintFilterCanvas)
612 {
613     // if canvas alpha is 1.0 or 0.0 - result is same
614     float canvasAlpha = paintFilterCanvas.GetAlpha();
615     float newAlpha = 1.0f;
616     if (ROSEN_EQ(canvasAlpha, 1.0f) || ROSEN_EQ(canvasAlpha, 0.0f)) {
617         return newAlpha;
618     }
619     auto maskColorShaderFilter = GetShaderFilterWithType(RSUIFilterType::MASK_COLOR);
620     if (maskColorShaderFilter != nullptr) {
621         auto maskColorFilter = std::static_pointer_cast<RSMaskColorShaderFilter>(maskColorShaderFilter);
622         float postAlpha = maskColorFilter->GetPostProcessAlpha();
623         newAlpha = (1.0f - postAlpha) / (1.0f - postAlpha  * canvasAlpha);
624     }
625     paintFilterCanvas.SetAlpha(1.0f);
626     return newAlpha * canvasAlpha;
627 }
628 
DrawImageRectInternal(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> image,const DrawImageRectAttributes & attr)629 void RSDrawingFilter::DrawImageRectInternal(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image> image,
630     const DrawImageRectAttributes& attr)
631 {
632     if (visualEffectContainer_ == nullptr) {
633         ROSEN_LOGE("RSDrawingFilter::DrawImageRect visualEffectContainer is null");
634         return;
635     }
636     auto kawaseHpsFilter = std::any_of(shaderFilters_.begin(), shaderFilters_.end(), [](const auto& filter) {
637         // If this Kawase skip is removed, set the compatiblity switch
638         // for HpsGEImageEffectContext to false in ApplyHpsImageEffect()
639         return filter->GetType() == RSUIFilterType::KAWASE;
640     });
641     auto brush = GetBrush(attr.brushAlpha);
642     if (attr.discardCanvas && kawaseHpsFilter && ROSEN_EQ(brush.GetColor().GetAlphaF(), 1.0f)) {
643         canvas.Discard();
644     }
645     ApplyImageEffect(canvas, image, visualEffectContainer_, attr);
646 }
647 
DrawImageRect(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> image,const Drawing::Rect & src,const Drawing::Rect & dst,const DrawImageRectParams params)648 void RSDrawingFilter::DrawImageRect(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image> image,
649     const Drawing::Rect& src, const Drawing::Rect& dst, const DrawImageRectParams params)
650 {
651     float canvasAlpha = canvas.GetAlpha();
652     DrawImageRectAttributes attr = { src, dst, params.discardCanvas, 1.0f };
653     if (params.offscreenDraw || ROSEN_EQ(canvasAlpha, 1.0f) || ROSEN_EQ(canvasAlpha, 0.0f)) {
654         DrawImageRectInternal(canvas, image, attr);
655         return;
656     }
657     // Only RSPaintFilterCanvas can have non-zero alpha stack
658     auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
659     RSAutoCanvasRestore autoCanvasRestore(paintFilterCanvas, RSPaintFilterCanvas::kAlpha);
660     attr.brushAlpha = PrepareAlphaForOnScreenDraw(*paintFilterCanvas);
661     DrawImageRectInternal(canvas, image, attr);
662 }
663 
PreProcess(std::shared_ptr<Drawing::Image> & image)664 void RSDrawingFilter::PreProcess(std::shared_ptr<Drawing::Image>& image)
665 {
666     std::for_each(shaderFilters_.begin(), shaderFilters_.end(), [&](auto& filter) {
667         filter->PreProcess(image);
668     });
669 }
670 
PostProcess(Drawing::Canvas & canvas)671 void RSDrawingFilter::PostProcess(Drawing::Canvas& canvas)
672 {
673     std::for_each(shaderFilters_.begin(), shaderFilters_.end(), [&](auto& filter) {
674         if ((!canSkipMaskColor_) || (!(filter->GetType() == RSUIFilterType::MASK_COLOR))) {
675             filter->PostProcess(canvas);
676         }
677     });
678 }
679 
NeedForceSubmit() const680 bool RSDrawingFilter::NeedForceSubmit() const
681 {
682     auto found = find_if(shaderFilters_.begin(), shaderFilters_.end(),
683         [](const auto& filter) { return filter != nullptr && filter->NeedForceSubmit(); });
684     return found != shaderFilters_.end();
685 }
686 } // namespace Rosen
687 } // namespace OHOS
688