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